{-# LANGUAGE CPP #-}
module Simplify ( simplTopBinds, simplExpr, simplRules ) where
#include "HsVersions.h"
import GhcPrelude
import DynFlags
import SimplMonad
import Type hiding ( substTy, substTyVar, extendTvSubst, extendCvSubst )
import SimplEnv
import SimplUtils
import OccurAnal ( occurAnalyseExpr )
import FamInstEnv ( FamInstEnv )
import Literal ( litIsLifted )
import Id
import MkId ( seqId )
import MkCore ( mkImpossibleExpr, castBottomExpr )
import IdInfo
import Name ( mkSystemVarName, isExternalName, getOccFS )
import Coercion hiding ( substCo, substCoVar )
import OptCoercion ( optCoercion )
import FamInstEnv ( topNormaliseType_maybe )
import DataCon ( DataCon, dataConWorkId, dataConRepStrictness
, dataConRepArgTys, isUnboxedTupleCon
, StrictnessMark (..) )
import CoreMonad ( Tick(..), SimplMode(..) )
import CoreSyn
import Demand ( StrictSig(..), dmdTypeDepth, isStrictDmd )
import PprCore ( pprCoreExpr )
import CoreUnfold
import CoreUtils
import CoreOpt ( pushCoTyArg, pushCoValArg
, joinPointBinding_maybe, joinPointBindings_maybe )
import Rules ( mkRuleInfo, lookupRule, getRules )
import Demand ( mkClosedStrictSig, topDmd, exnRes )
import BasicTypes ( TopLevelFlag(..), isNotTopLevel, isTopLevel,
RecFlag(..), Arity )
import MonadUtils ( mapAccumLM, liftIO )
import Var ( isTyCoVar )
import Maybes ( orElse )
import Control.Monad
import Outputable
import FastString
import Pair
import Util
import ErrUtils
import Module ( moduleName, pprModuleName )
import PrimOp ( PrimOp (SeqOp) )
simplTopBinds :: SimplEnv -> [InBind] -> SimplM (SimplFloats, SimplEnv)
simplTopBinds :: SimplEnv -> [InBind] -> SimplM (SimplFloats, SimplEnv)
simplTopBinds env0 :: SimplEnv
env0 binds0 :: [InBind]
binds0
= do {
; SimplEnv
env1 <- {-#SCC "simplTopBinds-simplRecBndrs" #-} SimplEnv -> [InBndr] -> SimplM SimplEnv
simplRecBndrs SimplEnv
env0 ([InBind] -> [InBndr]
forall b. [Bind b] -> [b]
bindersOfBinds [InBind]
binds0)
; (floats :: SimplFloats
floats, env2 :: SimplEnv
env2) <- {-#SCC "simplTopBinds-simpl_binds" #-} SimplEnv -> [InBind] -> SimplM (SimplFloats, SimplEnv)
simpl_binds SimplEnv
env1 [InBind]
binds0
; Tick -> SimplM ()
freeTick Tick
SimplifierDone
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, SimplEnv
env2) }
where
simpl_binds :: SimplEnv -> [InBind] -> SimplM (SimplFloats, SimplEnv)
simpl_binds :: SimplEnv -> [InBind] -> SimplM (SimplFloats, SimplEnv)
simpl_binds env :: SimplEnv
env [] = (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplEnv
env)
simpl_binds env :: SimplEnv
env (bind :: InBind
bind:binds :: [InBind]
binds) = do { (float :: SimplFloats
float, env1 :: SimplEnv
env1) <- SimplEnv -> InBind -> SimplM (SimplFloats, SimplEnv)
simpl_bind SimplEnv
env InBind
bind
; (floats :: SimplFloats
floats, env2 :: SimplEnv
env2) <- SimplEnv -> [InBind] -> SimplM (SimplFloats, SimplEnv)
simpl_binds SimplEnv
env1 [InBind]
binds
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
float SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats, SimplEnv
env2) }
simpl_bind :: SimplEnv -> InBind -> SimplM (SimplFloats, SimplEnv)
simpl_bind env :: SimplEnv
env (Rec pairs :: [(InBndr, Expr InBndr)]
pairs)
= SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> [(InBndr, Expr InBndr)]
-> SimplM (SimplFloats, SimplEnv)
simplRecBind SimplEnv
env TopLevelFlag
TopLevel MaybeJoinCont
forall a. Maybe a
Nothing [(InBndr, Expr InBndr)]
pairs
simpl_bind env :: SimplEnv
env (NonRec b :: InBndr
b r :: Expr InBndr
r)
= do { (env' :: SimplEnv
env', b' :: InBndr
b') <- SimplEnv
-> InBndr -> InBndr -> MaybeJoinCont -> SimplM (SimplEnv, InBndr)
addBndrRules SimplEnv
env InBndr
b (SimplEnv -> InBndr -> InBndr
lookupRecBndr SimplEnv
env InBndr
b) MaybeJoinCont
forall a. Maybe a
Nothing
; SimplEnv
-> TopLevelFlag
-> RecFlag
-> MaybeJoinCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
simplRecOrTopPair SimplEnv
env' TopLevelFlag
TopLevel RecFlag
NonRecursive MaybeJoinCont
forall a. Maybe a
Nothing InBndr
b InBndr
b' Expr InBndr
r }
simplRecBind :: SimplEnv -> TopLevelFlag -> MaybeJoinCont
-> [(InId, InExpr)]
-> SimplM (SimplFloats, SimplEnv)
simplRecBind :: SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> [(InBndr, Expr InBndr)]
-> SimplM (SimplFloats, SimplEnv)
simplRecBind env0 :: SimplEnv
env0 top_lvl :: TopLevelFlag
top_lvl mb_cont :: MaybeJoinCont
mb_cont pairs0 :: [(InBndr, Expr InBndr)]
pairs0
= do { (env_with_info :: SimplEnv
env_with_info, triples :: [(InBndr, InBndr, Expr InBndr)]
triples) <- (SimplEnv
-> (InBndr, Expr InBndr)
-> SimplM (SimplEnv, (InBndr, InBndr, Expr InBndr)))
-> SimplEnv
-> [(InBndr, Expr InBndr)]
-> SimplM (SimplEnv, [(InBndr, InBndr, Expr InBndr)])
forall (m :: * -> *) acc x y.
Monad m =>
(acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
mapAccumLM SimplEnv
-> (InBndr, Expr InBndr)
-> SimplM (SimplEnv, (InBndr, InBndr, Expr InBndr))
add_rules SimplEnv
env0 [(InBndr, Expr InBndr)]
pairs0
; (rec_floats :: SimplFloats
rec_floats, env1 :: SimplEnv
env1) <- SimplEnv
-> [(InBndr, InBndr, Expr InBndr)]
-> SimplM (SimplFloats, SimplEnv)
go SimplEnv
env_with_info [(InBndr, InBndr, Expr InBndr)]
triples
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats -> SimplFloats
mkRecFloats SimplFloats
rec_floats, SimplEnv
env1) }
where
add_rules :: SimplEnv -> (InBndr,InExpr) -> SimplM (SimplEnv, (InBndr, OutBndr, InExpr))
add_rules :: SimplEnv
-> (InBndr, Expr InBndr)
-> SimplM (SimplEnv, (InBndr, InBndr, Expr InBndr))
add_rules env :: SimplEnv
env (bndr :: InBndr
bndr, rhs :: Expr InBndr
rhs)
= do { (env' :: SimplEnv
env', bndr' :: InBndr
bndr') <- SimplEnv
-> InBndr -> InBndr -> MaybeJoinCont -> SimplM (SimplEnv, InBndr)
addBndrRules SimplEnv
env InBndr
bndr (SimplEnv -> InBndr -> InBndr
lookupRecBndr SimplEnv
env InBndr
bndr) MaybeJoinCont
mb_cont
; (SimplEnv, (InBndr, InBndr, Expr InBndr))
-> SimplM (SimplEnv, (InBndr, InBndr, Expr InBndr))
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env', (InBndr
bndr, InBndr
bndr', Expr InBndr
rhs)) }
go :: SimplEnv
-> [(InBndr, InBndr, Expr InBndr)]
-> SimplM (SimplFloats, SimplEnv)
go env :: SimplEnv
env [] = (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplEnv
env)
go env :: SimplEnv
env ((old_bndr :: InBndr
old_bndr, new_bndr :: InBndr
new_bndr, rhs :: Expr InBndr
rhs) : pairs :: [(InBndr, InBndr, Expr InBndr)]
pairs)
= do { (float :: SimplFloats
float, env1 :: SimplEnv
env1) <- SimplEnv
-> TopLevelFlag
-> RecFlag
-> MaybeJoinCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
simplRecOrTopPair SimplEnv
env TopLevelFlag
top_lvl RecFlag
Recursive MaybeJoinCont
mb_cont
InBndr
old_bndr InBndr
new_bndr Expr InBndr
rhs
; (floats :: SimplFloats
floats, env2 :: SimplEnv
env2) <- SimplEnv
-> [(InBndr, InBndr, Expr InBndr)]
-> SimplM (SimplFloats, SimplEnv)
go SimplEnv
env1 [(InBndr, InBndr, Expr InBndr)]
pairs
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
float SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats, SimplEnv
env2) }
simplRecOrTopPair :: SimplEnv
-> TopLevelFlag -> RecFlag -> MaybeJoinCont
-> InId -> OutBndr -> InExpr
-> SimplM (SimplFloats, SimplEnv)
simplRecOrTopPair :: SimplEnv
-> TopLevelFlag
-> RecFlag
-> MaybeJoinCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
simplRecOrTopPair env :: SimplEnv
env top_lvl :: TopLevelFlag
top_lvl is_rec :: RecFlag
is_rec mb_cont :: MaybeJoinCont
mb_cont old_bndr :: InBndr
old_bndr new_bndr :: InBndr
new_bndr rhs :: Expr InBndr
rhs
| Just env' :: SimplEnv
env' <- SimplEnv
-> TopLevelFlag
-> InBndr
-> Expr InBndr
-> SimplEnv
-> Maybe SimplEnv
preInlineUnconditionally SimplEnv
env TopLevelFlag
top_lvl InBndr
old_bndr Expr InBndr
rhs SimplEnv
env
= {-#SCC "simplRecOrTopPair-pre-inline-uncond" #-}
[Char]
-> SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall a. [Char] -> a -> a
trace_bind "pre-inline-uncond" (SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv))
-> SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall a b. (a -> b) -> a -> b
$
do { Tick -> SimplM ()
tick (InBndr -> Tick
PreInlineUnconditionally InBndr
old_bndr)
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return ( SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplEnv
env' ) }
| Just cont :: SimplCont
cont <- MaybeJoinCont
mb_cont
= {-#SCC "simplRecOrTopPair-join" #-}
ASSERT( isNotTopLevel top_lvl && isJoinId new_bndr )
[Char]
-> SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall a. [Char] -> a -> a
trace_bind "join" (SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv))
-> SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall a b. (a -> b) -> a -> b
$
SimplEnv
-> SimplCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplJoinBind SimplEnv
env SimplCont
cont InBndr
old_bndr InBndr
new_bndr Expr InBndr
rhs SimplEnv
env
| Bool
otherwise
= {-#SCC "simplRecOrTopPair-normal" #-}
[Char]
-> SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall a. [Char] -> a -> a
trace_bind "normal" (SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv))
-> SimplM (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall a b. (a -> b) -> a -> b
$
SimplEnv
-> TopLevelFlag
-> RecFlag
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplLazyBind SimplEnv
env TopLevelFlag
top_lvl RecFlag
is_rec InBndr
old_bndr InBndr
new_bndr Expr InBndr
rhs SimplEnv
env
where
dflags :: DynFlags
dflags = SimplEnv -> DynFlags
seDynFlags SimplEnv
env
trace_bind :: [Char] -> a -> a
trace_bind what :: [Char]
what thing_inside :: a
thing_inside
| Bool -> Bool
not (DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_verbose_core2core DynFlags
dflags)
= a
thing_inside
| Bool
otherwise
= [Char] -> SDoc -> a -> a
forall a. [Char] -> SDoc -> a -> a
pprTrace ("SimplBind " [Char] -> [Char] -> [Char]
forall a. [a] -> [a] -> [a]
++ [Char]
what) (InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
old_bndr) a
thing_inside
simplLazyBind :: SimplEnv
-> TopLevelFlag -> RecFlag
-> InId -> OutId
-> InExpr -> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplLazyBind :: SimplEnv
-> TopLevelFlag
-> RecFlag
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplLazyBind env :: SimplEnv
env top_lvl :: TopLevelFlag
top_lvl is_rec :: RecFlag
is_rec bndr :: InBndr
bndr bndr1 :: InBndr
bndr1 rhs :: Expr InBndr
rhs rhs_se :: SimplEnv
rhs_se
= ASSERT( isId bndr )
ASSERT2( not (isJoinId bndr), ppr bndr )
do { let rhs_env :: SimplEnv
rhs_env = SimplEnv
rhs_se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env
(tvs :: [InBndr]
tvs, body :: Expr InBndr
body) = case Expr InBndr -> ([InBndr], [InBndr], Expr InBndr)
collectTyAndValBinders Expr InBndr
rhs of
(tvs :: [InBndr]
tvs, [], body :: Expr InBndr
body)
| Expr InBndr -> Bool
forall b. Expr b -> Bool
surely_not_lam Expr InBndr
body -> ([InBndr]
tvs, Expr InBndr
body)
_ -> ([], Expr InBndr
rhs)
surely_not_lam :: Expr b -> Bool
surely_not_lam (Lam {}) = Bool
False
surely_not_lam (Tick t :: Tickish InBndr
t e :: Expr b
e)
| Bool -> Bool
not (Tickish InBndr -> Bool
forall id. Tickish id -> Bool
tickishFloatable Tickish InBndr
t) = Expr b -> Bool
surely_not_lam Expr b
e
surely_not_lam _ = Bool
True
; (body_env :: SimplEnv
body_env, tvs' :: [InBndr]
tvs') <- {-#SCC "simplBinders" #-} SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
simplBinders SimplEnv
rhs_env [InBndr]
tvs
; let rhs_cont :: SimplCont
rhs_cont = OutType -> SimplCont
mkRhsStop (SimplEnv -> OutType -> OutType
substTy SimplEnv
body_env (Expr InBndr -> OutType
exprType Expr InBndr
body))
; (body_floats0 :: SimplFloats
body_floats0, body0 :: Expr InBndr
body0) <- {-#SCC "simplExprF" #-} SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
body_env Expr InBndr
body SimplCont
rhs_cont
; let (body_floats1 :: SimplFloats
body_floats1, body1 :: Expr InBndr
body1) = SimplFloats -> Expr InBndr -> (SimplFloats, Expr InBndr)
wrapJoinFloatsX SimplFloats
body_floats0 Expr InBndr
body0
; (let_floats :: LetFloats
let_floats, body2 :: Expr InBndr
body2) <- {-#SCC "prepareRhs" #-} SimplMode
-> TopLevelFlag
-> FastString
-> IdInfo
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
prepareRhs (SimplEnv -> SimplMode
getMode SimplEnv
env) TopLevelFlag
top_lvl
(InBndr -> FastString
forall a. NamedThing a => a -> FastString
getOccFS InBndr
bndr1) (HasDebugCallStack => InBndr -> IdInfo
InBndr -> IdInfo
idInfo InBndr
bndr1) Expr InBndr
body1
; let body_floats2 :: SimplFloats
body_floats2 = SimplFloats
body_floats1 SimplFloats -> LetFloats -> SimplFloats
`addLetFloats` LetFloats
let_floats
; (rhs_floats :: SimplFloats
rhs_floats, rhs' :: Expr InBndr
rhs')
<- if Bool -> Bool
not (TopLevelFlag
-> RecFlag -> Bool -> SimplFloats -> Expr InBndr -> Bool
doFloatFromRhs TopLevelFlag
top_lvl RecFlag
is_rec Bool
False SimplFloats
body_floats2 Expr InBndr
body2)
then
{-#SCC "simplLazyBind-no-floating" #-}
do { Expr InBndr
rhs' <- SimplEnv
-> [InBndr] -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
mkLam SimplEnv
env [InBndr]
tvs' (SimplFloats -> Expr InBndr -> Expr InBndr
wrapFloats SimplFloats
body_floats2 Expr InBndr
body1) SimplCont
rhs_cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, Expr InBndr
rhs') }
else if [InBndr] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [InBndr]
tvs then
{-#SCC "simplLazyBind-simple-floating" #-}
do { Tick -> SimplM ()
tick Tick
LetFloatFromLet
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
body_floats2, Expr InBndr
body2) }
else
{-#SCC "simplLazyBind-type-abstraction-first" #-}
do { Tick -> SimplM ()
tick Tick
LetFloatFromLet
; (poly_binds :: [InBind]
poly_binds, body3 :: Expr InBndr
body3) <- DynFlags
-> TopLevelFlag
-> [InBndr]
-> SimplFloats
-> Expr InBndr
-> SimplM ([InBind], Expr InBndr)
abstractFloats (SimplEnv -> DynFlags
seDynFlags SimplEnv
env) TopLevelFlag
top_lvl
[InBndr]
tvs' SimplFloats
body_floats2 Expr InBndr
body2
; let floats :: SimplFloats
floats = (SimplFloats -> InBind -> SimplFloats)
-> SimplFloats -> [InBind] -> SimplFloats
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' SimplFloats -> InBind -> SimplFloats
extendFloats (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env) [InBind]
poly_binds
; Expr InBndr
rhs' <- SimplEnv
-> [InBndr] -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
mkLam SimplEnv
env [InBndr]
tvs' Expr InBndr
body3 SimplCont
rhs_cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, Expr InBndr
rhs') }
; (bind_float :: SimplFloats
bind_float, env2 :: SimplEnv
env2) <- SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
completeBind (SimplEnv
env SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
rhs_floats)
TopLevelFlag
top_lvl MaybeJoinCont
forall a. Maybe a
Nothing InBndr
bndr InBndr
bndr1 Expr InBndr
rhs'
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
rhs_floats SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
bind_float, SimplEnv
env2) }
simplJoinBind :: SimplEnv
-> SimplCont
-> InId -> OutId
-> InExpr -> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplJoinBind :: SimplEnv
-> SimplCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplJoinBind env :: SimplEnv
env cont :: SimplCont
cont old_bndr :: InBndr
old_bndr new_bndr :: InBndr
new_bndr rhs :: Expr InBndr
rhs rhs_se :: SimplEnv
rhs_se
= do { let rhs_env :: SimplEnv
rhs_env = SimplEnv
rhs_se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env
; Expr InBndr
rhs' <- SimplEnv
-> InBndr -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplJoinRhs SimplEnv
rhs_env InBndr
old_bndr Expr InBndr
rhs SimplCont
cont
; SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
completeBind SimplEnv
env TopLevelFlag
NotTopLevel (SimplCont -> MaybeJoinCont
forall a. a -> Maybe a
Just SimplCont
cont) InBndr
old_bndr InBndr
new_bndr Expr InBndr
rhs' }
simplNonRecX :: SimplEnv
-> InId
-> OutExpr
-> SimplM (SimplFloats, SimplEnv)
simplNonRecX :: SimplEnv -> InBndr -> Expr InBndr -> SimplM (SimplFloats, SimplEnv)
simplNonRecX env :: SimplEnv
env bndr :: InBndr
bndr new_rhs :: Expr InBndr
new_rhs
| ASSERT2( not (isJoinId bndr), ppr bndr )
InBndr -> Bool
isDeadBinder InBndr
bndr
= (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplEnv
env)
| Coercion co :: Coercion
co <- Expr InBndr
new_rhs
= (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplEnv -> InBndr -> Coercion -> SimplEnv
extendCvSubst SimplEnv
env InBndr
bndr Coercion
co)
| Bool
otherwise
= do { (env' :: SimplEnv
env', bndr' :: InBndr
bndr') <- SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplBinder SimplEnv
env InBndr
bndr
; TopLevelFlag
-> SimplEnv
-> Bool
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
completeNonRecX TopLevelFlag
NotTopLevel SimplEnv
env' (InBndr -> Bool
isStrictId InBndr
bndr) InBndr
bndr InBndr
bndr' Expr InBndr
new_rhs }
completeNonRecX :: TopLevelFlag -> SimplEnv
-> Bool
-> InId
-> OutId
-> OutExpr
-> SimplM (SimplFloats, SimplEnv)
completeNonRecX :: TopLevelFlag
-> SimplEnv
-> Bool
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
completeNonRecX top_lvl :: TopLevelFlag
top_lvl env :: SimplEnv
env is_strict :: Bool
is_strict old_bndr :: InBndr
old_bndr new_bndr :: InBndr
new_bndr new_rhs :: Expr InBndr
new_rhs
= ASSERT2( not (isJoinId new_bndr), ppr new_bndr )
do { (prepd_floats :: LetFloats
prepd_floats, rhs1 :: Expr InBndr
rhs1) <- SimplMode
-> TopLevelFlag
-> FastString
-> IdInfo
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
prepareRhs (SimplEnv -> SimplMode
getMode SimplEnv
env) TopLevelFlag
top_lvl (InBndr -> FastString
forall a. NamedThing a => a -> FastString
getOccFS InBndr
new_bndr)
(HasDebugCallStack => InBndr -> IdInfo
InBndr -> IdInfo
idInfo InBndr
new_bndr) Expr InBndr
new_rhs
; let floats :: SimplFloats
floats = SimplEnv -> SimplFloats
emptyFloats SimplEnv
env SimplFloats -> LetFloats -> SimplFloats
`addLetFloats` LetFloats
prepd_floats
; (rhs_floats :: SimplFloats
rhs_floats, rhs2 :: Expr InBndr
rhs2) <-
if TopLevelFlag
-> RecFlag -> Bool -> SimplFloats -> Expr InBndr -> Bool
doFloatFromRhs TopLevelFlag
NotTopLevel RecFlag
NonRecursive Bool
is_strict SimplFloats
floats Expr InBndr
rhs1
then
do { Tick -> SimplM ()
tick Tick
LetFloatFromLet
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, Expr InBndr
rhs1) }
else
(SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplFloats -> Expr InBndr -> Expr InBndr
wrapFloats SimplFloats
floats Expr InBndr
rhs1)
; (bind_float :: SimplFloats
bind_float, env2 :: SimplEnv
env2) <- SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
completeBind (SimplEnv
env SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
rhs_floats)
TopLevelFlag
NotTopLevel MaybeJoinCont
forall a. Maybe a
Nothing
InBndr
old_bndr InBndr
new_bndr Expr InBndr
rhs2
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
rhs_floats SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
bind_float, SimplEnv
env2) }
prepareRhs :: SimplMode -> TopLevelFlag
-> FastString
-> IdInfo
-> OutExpr
-> SimplM (LetFloats, OutExpr)
prepareRhs :: SimplMode
-> TopLevelFlag
-> FastString
-> IdInfo
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
prepareRhs mode :: SimplMode
mode top_lvl :: TopLevelFlag
top_lvl occ :: FastString
occ info :: IdInfo
info (Cast rhs :: Expr InBndr
rhs co :: Coercion
co)
| Pair ty1 :: OutType
ty1 _ty2 :: OutType
_ty2 <- Coercion -> Pair OutType
coercionKind Coercion
co
, Bool -> Bool
not (HasDebugCallStack => OutType -> Bool
OutType -> Bool
isUnliftedType OutType
ty1)
= do { (floats :: LetFloats
floats, rhs' :: Expr InBndr
rhs') <- SimplMode
-> TopLevelFlag
-> FastString
-> IdInfo
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
makeTrivialWithInfo SimplMode
mode TopLevelFlag
top_lvl FastString
occ IdInfo
sanitised_info Expr InBndr
rhs
; (LetFloats, Expr InBndr) -> SimplM (LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (LetFloats
floats, Expr InBndr -> Coercion -> Expr InBndr
forall b. Expr b -> Coercion -> Expr b
Cast Expr InBndr
rhs' Coercion
co) }
where
sanitised_info :: IdInfo
sanitised_info = IdInfo
vanillaIdInfo IdInfo -> StrictSig -> IdInfo
`setStrictnessInfo` IdInfo -> StrictSig
strictnessInfo IdInfo
info
IdInfo -> Demand -> IdInfo
`setDemandInfo` IdInfo -> Demand
demandInfo IdInfo
info
prepareRhs mode :: SimplMode
mode top_lvl :: TopLevelFlag
top_lvl occ :: FastString
occ _ rhs0 :: Expr InBndr
rhs0
= do { (_is_exp :: Bool
_is_exp, floats :: LetFloats
floats, rhs1 :: Expr InBndr
rhs1) <- Int -> Expr InBndr -> SimplM (Bool, LetFloats, Expr InBndr)
go 0 Expr InBndr
rhs0
; (LetFloats, Expr InBndr) -> SimplM (LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (LetFloats
floats, Expr InBndr
rhs1) }
where
go :: Int -> OutExpr -> SimplM (Bool, LetFloats, OutExpr)
go :: Int -> Expr InBndr -> SimplM (Bool, LetFloats, Expr InBndr)
go n_val_args :: Int
n_val_args (Cast rhs :: Expr InBndr
rhs co :: Coercion
co)
= do { (is_exp :: Bool
is_exp, floats :: LetFloats
floats, rhs' :: Expr InBndr
rhs') <- Int -> Expr InBndr -> SimplM (Bool, LetFloats, Expr InBndr)
go Int
n_val_args Expr InBndr
rhs
; (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
is_exp, LetFloats
floats, Expr InBndr -> Coercion -> Expr InBndr
forall b. Expr b -> Coercion -> Expr b
Cast Expr InBndr
rhs' Coercion
co) }
go n_val_args :: Int
n_val_args (App fun :: Expr InBndr
fun (Type ty :: OutType
ty))
= do { (is_exp :: Bool
is_exp, floats :: LetFloats
floats, rhs' :: Expr InBndr
rhs') <- Int -> Expr InBndr -> SimplM (Bool, LetFloats, Expr InBndr)
go Int
n_val_args Expr InBndr
fun
; (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
is_exp, LetFloats
floats, Expr InBndr -> Expr InBndr -> Expr InBndr
forall b. Expr b -> Expr b -> Expr b
App Expr InBndr
rhs' (OutType -> Expr InBndr
forall b. OutType -> Expr b
Type OutType
ty)) }
go n_val_args :: Int
n_val_args (App fun :: Expr InBndr
fun arg :: Expr InBndr
arg)
= do { (is_exp :: Bool
is_exp, floats1 :: LetFloats
floats1, fun' :: Expr InBndr
fun') <- Int -> Expr InBndr -> SimplM (Bool, LetFloats, Expr InBndr)
go (Int
n_val_argsInt -> Int -> Int
forall a. Num a => a -> a -> a
+1) Expr InBndr
fun
; case Bool
is_exp of
False -> (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, LetFloats
emptyLetFloats, Expr InBndr -> Expr InBndr -> Expr InBndr
forall b. Expr b -> Expr b -> Expr b
App Expr InBndr
fun Expr InBndr
arg)
True -> do { (floats2 :: LetFloats
floats2, arg' :: Expr InBndr
arg') <- SimplMode
-> TopLevelFlag
-> FastString
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
makeTrivial SimplMode
mode TopLevelFlag
top_lvl FastString
occ Expr InBndr
arg
; (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
True, LetFloats
floats1 LetFloats -> LetFloats -> LetFloats
`addLetFlts` LetFloats
floats2, Expr InBndr -> Expr InBndr -> Expr InBndr
forall b. Expr b -> Expr b -> Expr b
App Expr InBndr
fun' Expr InBndr
arg') } }
go n_val_args :: Int
n_val_args (Var fun :: InBndr
fun)
= (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
is_exp, LetFloats
emptyLetFloats, InBndr -> Expr InBndr
forall b. InBndr -> Expr b
Var InBndr
fun)
where
is_exp :: Bool
is_exp = CheapAppFun
isExpandableApp InBndr
fun Int
n_val_args
go n_val_args :: Int
n_val_args (Tick t :: Tickish InBndr
t rhs :: Expr InBndr
rhs)
| Tickish InBndr -> TickishScoping
forall id. Tickish id -> TickishScoping
tickishScoped Tickish InBndr
t TickishScoping -> TickishScoping -> Bool
forall a. Eq a => a -> a -> Bool
== TickishScoping
NoScope
= do { (is_exp :: Bool
is_exp, floats :: LetFloats
floats, rhs' :: Expr InBndr
rhs') <- Int -> Expr InBndr -> SimplM (Bool, LetFloats, Expr InBndr)
go Int
n_val_args Expr InBndr
rhs
; (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
is_exp, LetFloats
floats, Tickish InBndr -> Expr InBndr -> Expr InBndr
forall b. Tickish InBndr -> Expr b -> Expr b
Tick Tickish InBndr
t Expr InBndr
rhs') }
| (Bool -> Bool
not (Tickish InBndr -> Bool
forall id. Tickish id -> Bool
tickishCounts Tickish InBndr
t) Bool -> Bool -> Bool
|| Tickish InBndr -> Bool
forall id. Tickish id -> Bool
tickishCanSplit Tickish InBndr
t)
= do { (is_exp :: Bool
is_exp, floats :: LetFloats
floats, rhs' :: Expr InBndr
rhs') <- Int -> Expr InBndr -> SimplM (Bool, LetFloats, Expr InBndr)
go Int
n_val_args Expr InBndr
rhs
; let tickIt :: (a, Expr InBndr) -> (a, Expr InBndr)
tickIt (id :: a
id, expr :: Expr InBndr
expr) = (a
id, Tickish InBndr -> Expr InBndr -> Expr InBndr
mkTick (Tickish InBndr -> Tickish InBndr
forall id. Tickish id -> Tickish id
mkNoCount Tickish InBndr
t) Expr InBndr
expr)
floats' :: LetFloats
floats' = LetFloats
-> ((InBndr, Expr InBndr) -> (InBndr, Expr InBndr)) -> LetFloats
mapLetFloats LetFloats
floats (InBndr, Expr InBndr) -> (InBndr, Expr InBndr)
forall a. (a, Expr InBndr) -> (a, Expr InBndr)
tickIt
; (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
is_exp, LetFloats
floats', Tickish InBndr -> Expr InBndr -> Expr InBndr
forall b. Tickish InBndr -> Expr b -> Expr b
Tick Tickish InBndr
t Expr InBndr
rhs') }
go _ other :: Expr InBndr
other
= (Bool, LetFloats, Expr InBndr)
-> SimplM (Bool, LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Bool
False, LetFloats
emptyLetFloats, Expr InBndr
other)
makeTrivialArg :: SimplMode -> ArgSpec -> SimplM (LetFloats, ArgSpec)
makeTrivialArg :: SimplMode -> ArgSpec -> SimplM (LetFloats, ArgSpec)
makeTrivialArg mode :: SimplMode
mode (ValArg e :: Expr InBndr
e)
= do { (floats :: LetFloats
floats, e' :: Expr InBndr
e') <- SimplMode
-> TopLevelFlag
-> FastString
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
makeTrivial SimplMode
mode TopLevelFlag
NotTopLevel ([Char] -> FastString
fsLit "arg") Expr InBndr
e
; (LetFloats, ArgSpec) -> SimplM (LetFloats, ArgSpec)
forall (m :: * -> *) a. Monad m => a -> m a
return (LetFloats
floats, Expr InBndr -> ArgSpec
ValArg Expr InBndr
e') }
makeTrivialArg _ arg :: ArgSpec
arg
= (LetFloats, ArgSpec) -> SimplM (LetFloats, ArgSpec)
forall (m :: * -> *) a. Monad m => a -> m a
return (LetFloats
emptyLetFloats, ArgSpec
arg)
makeTrivial :: SimplMode -> TopLevelFlag
-> FastString
-> OutExpr
-> SimplM (LetFloats, OutExpr)
makeTrivial :: SimplMode
-> TopLevelFlag
-> FastString
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
makeTrivial mode :: SimplMode
mode top_lvl :: TopLevelFlag
top_lvl context :: FastString
context expr :: Expr InBndr
expr
= SimplMode
-> TopLevelFlag
-> FastString
-> IdInfo
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
makeTrivialWithInfo SimplMode
mode TopLevelFlag
top_lvl FastString
context IdInfo
vanillaIdInfo Expr InBndr
expr
makeTrivialWithInfo :: SimplMode -> TopLevelFlag
-> FastString
-> IdInfo
-> OutExpr
-> SimplM (LetFloats, OutExpr)
makeTrivialWithInfo :: SimplMode
-> TopLevelFlag
-> FastString
-> IdInfo
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
makeTrivialWithInfo mode :: SimplMode
mode top_lvl :: TopLevelFlag
top_lvl occ_fs :: FastString
occ_fs info :: IdInfo
info expr :: Expr InBndr
expr
| Expr InBndr -> Bool
exprIsTrivial Expr InBndr
expr
Bool -> Bool -> Bool
|| Bool -> Bool
not (TopLevelFlag -> Expr InBndr -> OutType -> Bool
bindingOk TopLevelFlag
top_lvl Expr InBndr
expr OutType
expr_ty)
= (LetFloats, Expr InBndr) -> SimplM (LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (LetFloats
emptyLetFloats, Expr InBndr
expr)
| Bool
otherwise
= do { (floats :: LetFloats
floats, expr1 :: Expr InBndr
expr1) <- SimplMode
-> TopLevelFlag
-> FastString
-> IdInfo
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
prepareRhs SimplMode
mode TopLevelFlag
top_lvl FastString
occ_fs IdInfo
info Expr InBndr
expr
; if Expr InBndr -> Bool
exprIsTrivial Expr InBndr
expr1
then (LetFloats, Expr InBndr) -> SimplM (LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (LetFloats
floats, Expr InBndr
expr1)
else do
{ Unique
uniq <- SimplM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let name :: Name
name = Unique -> FastString -> Name
mkSystemVarName Unique
uniq FastString
occ_fs
var :: InBndr
var = Name -> OutType -> IdInfo -> InBndr
mkLocalIdOrCoVarWithInfo Name
name OutType
expr_ty IdInfo
info
; (arity :: Int
arity, is_bot :: Bool
is_bot, expr2 :: Expr InBndr
expr2) <- SimplMode
-> InBndr -> Expr InBndr -> SimplM (Int, Bool, Expr InBndr)
tryEtaExpandRhs SimplMode
mode InBndr
var Expr InBndr
expr1
; Unfolding
unf <- DynFlags
-> TopLevelFlag
-> UnfoldingSource
-> InBndr
-> Expr InBndr
-> SimplM Unfolding
mkLetUnfolding (SimplMode -> DynFlags
sm_dflags SimplMode
mode) TopLevelFlag
top_lvl UnfoldingSource
InlineRhs InBndr
var Expr InBndr
expr2
; let final_id :: InBndr
final_id = InBndr -> Int -> Bool -> Unfolding -> InBndr
addLetBndrInfo InBndr
var Int
arity Bool
is_bot Unfolding
unf
bind :: InBind
bind = InBndr -> Expr InBndr -> InBind
forall b. b -> Expr b -> Bind b
NonRec InBndr
final_id Expr InBndr
expr2
; (LetFloats, Expr InBndr) -> SimplM (LetFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return ( LetFloats
floats LetFloats -> LetFloats -> LetFloats
`addLetFlts` InBind -> LetFloats
unitLetFloat InBind
bind, InBndr -> Expr InBndr
forall b. InBndr -> Expr b
Var InBndr
final_id ) }}
where
expr_ty :: OutType
expr_ty = Expr InBndr -> OutType
exprType Expr InBndr
expr
bindingOk :: TopLevelFlag -> CoreExpr -> Type -> Bool
bindingOk :: TopLevelFlag -> Expr InBndr -> OutType -> Bool
bindingOk top_lvl :: TopLevelFlag
top_lvl expr :: Expr InBndr
expr expr_ty :: OutType
expr_ty
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl = Expr InBndr -> OutType -> Bool
exprIsTopLevelBindable Expr InBndr
expr OutType
expr_ty
| Bool
otherwise = Bool
True
completeBind :: SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InId
-> OutId -> OutExpr
-> SimplM (SimplFloats, SimplEnv)
completeBind :: SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplM (SimplFloats, SimplEnv)
completeBind env :: SimplEnv
env top_lvl :: TopLevelFlag
top_lvl mb_cont :: MaybeJoinCont
mb_cont old_bndr :: InBndr
old_bndr new_bndr :: InBndr
new_bndr new_rhs :: Expr InBndr
new_rhs
| InBndr -> Bool
isCoVar InBndr
old_bndr
= case Expr InBndr
new_rhs of
Coercion co :: Coercion
co -> (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplEnv -> InBndr -> Coercion -> SimplEnv
extendCvSubst SimplEnv
env InBndr
old_bndr Coercion
co)
_ -> (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> InBind -> (SimplFloats, SimplEnv)
mkFloatBind SimplEnv
env (InBndr -> Expr InBndr -> InBind
forall b. b -> Expr b -> Bind b
NonRec InBndr
new_bndr Expr InBndr
new_rhs))
| Bool
otherwise
= ASSERT( isId new_bndr )
do { let old_info :: IdInfo
old_info = HasDebugCallStack => InBndr -> IdInfo
InBndr -> IdInfo
idInfo InBndr
old_bndr
old_unf :: Unfolding
old_unf = IdInfo -> Unfolding
unfoldingInfo IdInfo
old_info
occ_info :: OccInfo
occ_info = IdInfo -> OccInfo
occInfo IdInfo
old_info
; (new_arity :: Int
new_arity, is_bot :: Bool
is_bot, final_rhs :: Expr InBndr
final_rhs) <- SimplMode
-> InBndr -> Expr InBndr -> SimplM (Int, Bool, Expr InBndr)
tryEtaExpandRhs (SimplEnv -> SimplMode
getMode SimplEnv
env)
InBndr
new_bndr Expr InBndr
new_rhs
; Unfolding
new_unfolding <- SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> Expr InBndr
-> OutType
-> Unfolding
-> SimplM Unfolding
simplLetUnfolding SimplEnv
env TopLevelFlag
top_lvl MaybeJoinCont
mb_cont InBndr
old_bndr
Expr InBndr
final_rhs (InBndr -> OutType
idType InBndr
new_bndr) Unfolding
old_unf
; let final_bndr :: InBndr
final_bndr = InBndr -> Int -> Bool -> Unfolding -> InBndr
addLetBndrInfo InBndr
new_bndr Int
new_arity Bool
is_bot Unfolding
new_unfolding
; if SimplEnv
-> TopLevelFlag -> InBndr -> OccInfo -> Expr InBndr -> Bool
postInlineUnconditionally SimplEnv
env TopLevelFlag
top_lvl InBndr
final_bndr OccInfo
occ_info Expr InBndr
final_rhs
then
do { Tick -> SimplM ()
tick (InBndr -> Tick
PostInlineUnconditionally InBndr
old_bndr)
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return ( SimplEnv -> SimplFloats
emptyFloats SimplEnv
env
, SimplEnv -> InBndr -> SimplSR -> SimplEnv
extendIdSubst SimplEnv
env InBndr
old_bndr (SimplSR -> SimplEnv) -> SimplSR -> SimplEnv
forall a b. (a -> b) -> a -> b
$
Expr InBndr -> Maybe Int -> SimplSR
DoneEx Expr InBndr
final_rhs (InBndr -> Maybe Int
isJoinId_maybe InBndr
new_bndr)) }
else
(SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> InBind -> (SimplFloats, SimplEnv)
mkFloatBind SimplEnv
env (InBndr -> Expr InBndr -> InBind
forall b. b -> Expr b -> Bind b
NonRec InBndr
final_bndr Expr InBndr
final_rhs)) }
addLetBndrInfo :: OutId -> Arity -> Bool -> Unfolding -> OutId
addLetBndrInfo :: InBndr -> Int -> Bool -> Unfolding -> InBndr
addLetBndrInfo new_bndr :: InBndr
new_bndr new_arity :: Int
new_arity is_bot :: Bool
is_bot new_unf :: Unfolding
new_unf
= InBndr
new_bndr InBndr -> IdInfo -> InBndr
`setIdInfo` IdInfo
info5
where
info1 :: IdInfo
info1 = HasDebugCallStack => InBndr -> IdInfo
InBndr -> IdInfo
idInfo InBndr
new_bndr IdInfo -> Int -> IdInfo
`setArityInfo` Int
new_arity
info2 :: IdInfo
info2 = IdInfo
info1 IdInfo -> Unfolding -> IdInfo
`setUnfoldingInfo` Unfolding
new_unf
info3 :: IdInfo
info3 | Unfolding -> Bool
isEvaldUnfolding Unfolding
new_unf
Bool -> Bool -> Bool
|| (case IdInfo -> StrictSig
strictnessInfo IdInfo
info2 of
StrictSig dmd_ty :: DmdType
dmd_ty -> Int
new_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
< DmdType -> Int
dmdTypeDepth DmdType
dmd_ty)
= IdInfo -> Maybe IdInfo
zapDemandInfo IdInfo
info2 Maybe IdInfo -> IdInfo -> IdInfo
forall a. Maybe a -> a -> a
`orElse` IdInfo
info2
| Bool
otherwise
= IdInfo
info2
info4 :: IdInfo
info4 | Bool
is_bot = IdInfo
info3 IdInfo -> StrictSig -> IdInfo
`setStrictnessInfo`
[Demand] -> DmdResult -> StrictSig
mkClosedStrictSig (Int -> Demand -> [Demand]
forall a. Int -> a -> [a]
replicate Int
new_arity Demand
topDmd) DmdResult
exnRes
| Bool
otherwise = IdInfo
info3
info5 :: IdInfo
info5 = IdInfo -> IdInfo
zapCallArityInfo IdInfo
info4
simplExpr :: SimplEnv -> CoreExpr -> SimplM CoreExpr
simplExpr :: SimplEnv -> Expr InBndr -> SimplM (Expr InBndr)
simplExpr env :: SimplEnv
env (Type ty :: OutType
ty)
= do { OutType
ty' <- SimplEnv -> OutType -> SimplM OutType
simplType SimplEnv
env OutType
ty
; Expr InBndr -> SimplM (Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OutType -> Expr InBndr
forall b. OutType -> Expr b
Type OutType
ty') }
simplExpr env :: SimplEnv
env expr :: Expr InBndr
expr
= SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC SimplEnv
env Expr InBndr
expr (OutType -> SimplCont
mkBoringStop OutType
expr_out_ty)
where
expr_out_ty :: OutType
expr_out_ty :: OutType
expr_out_ty = SimplEnv -> OutType -> OutType
substTy SimplEnv
env (Expr InBndr -> OutType
exprType Expr InBndr
expr)
simplExprC :: SimplEnv
-> InExpr
-> SimplCont
-> SimplM OutExpr
simplExprC :: SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC env :: SimplEnv
env expr :: Expr InBndr
expr cont :: SimplCont
cont
=
do { (floats :: SimplFloats
floats, expr' :: Expr InBndr
expr') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
expr SimplCont
cont
;
Expr InBndr -> SimplM (Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats -> Expr InBndr -> Expr InBndr
wrapFloats SimplFloats
floats Expr InBndr
expr') }
simplExprF :: SimplEnv
-> InExpr
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplExprF :: SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF env :: SimplEnv
env e :: Expr InBndr
e cont :: SimplCont
cont
=
SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF1 SimplEnv
env Expr InBndr
e SimplCont
cont
simplExprF1 :: SimplEnv -> InExpr -> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplExprF1 :: SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF1 _ (Type ty :: OutType
ty) _
= [Char] -> SDoc -> SimplM (SimplFloats, Expr InBndr)
forall a. HasCallStack => [Char] -> SDoc -> a
pprPanic "simplExprF: type" (OutType -> SDoc
forall a. Outputable a => a -> SDoc
ppr OutType
ty)
simplExprF1 env :: SimplEnv
env (Var v :: InBndr
v) cont :: SimplCont
cont = {-#SCC "simplIdF" #-} SimplEnv
-> InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplIdF SimplEnv
env InBndr
v SimplCont
cont
simplExprF1 env :: SimplEnv
env (Lit lit :: Literal
lit) cont :: SimplCont
cont = {-#SCC "rebuild" #-} SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (Literal -> Expr InBndr
forall b. Literal -> Expr b
Lit Literal
lit) SimplCont
cont
simplExprF1 env :: SimplEnv
env (Tick t :: Tickish InBndr
t expr :: Expr InBndr
expr) cont :: SimplCont
cont = {-#SCC "simplTick" #-} SimplEnv
-> Tickish InBndr
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplTick SimplEnv
env Tickish InBndr
t Expr InBndr
expr SimplCont
cont
simplExprF1 env :: SimplEnv
env (Cast body :: Expr InBndr
body co :: Coercion
co) cont :: SimplCont
cont = {-#SCC "simplCast" #-} SimplEnv
-> Expr InBndr
-> Coercion
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplCast SimplEnv
env Expr InBndr
body Coercion
co SimplCont
cont
simplExprF1 env :: SimplEnv
env (Coercion co :: Coercion
co) cont :: SimplCont
cont = {-#SCC "simplCoercionF" #-} SimplEnv
-> Coercion -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplCoercionF SimplEnv
env Coercion
co SimplCont
cont
simplExprF1 env :: SimplEnv
env (App fun :: Expr InBndr
fun arg :: Expr InBndr
arg) cont :: SimplCont
cont
= {-#SCC "simplExprF1-App" #-} case Expr InBndr
arg of
Type ty :: OutType
ty -> do {
OutType
arg' <- SimplEnv -> OutType -> SimplM OutType
simplType SimplEnv
env OutType
ty
; let hole' :: OutType
hole' = SimplEnv -> OutType -> OutType
substTy SimplEnv
env (Expr InBndr -> OutType
exprType Expr InBndr
fun)
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
fun (SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplCont -> SimplM (SimplFloats, Expr InBndr)
forall a b. (a -> b) -> a -> b
$
ApplyToTy :: OutType -> OutType -> SimplCont -> SimplCont
ApplyToTy { sc_arg_ty :: OutType
sc_arg_ty = OutType
arg'
, sc_hole_ty :: OutType
sc_hole_ty = OutType
hole'
, sc_cont :: SimplCont
sc_cont = SimplCont
cont } }
_ -> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
fun (SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplCont -> SimplM (SimplFloats, Expr InBndr)
forall a b. (a -> b) -> a -> b
$
ApplyToVal :: DupFlag -> Expr InBndr -> SimplEnv -> SimplCont -> SimplCont
ApplyToVal { sc_arg :: Expr InBndr
sc_arg = Expr InBndr
arg, sc_env :: SimplEnv
sc_env = SimplEnv
env
, sc_dup :: DupFlag
sc_dup = DupFlag
NoDup, sc_cont :: SimplCont
sc_cont = SimplCont
cont }
simplExprF1 env :: SimplEnv
env expr :: Expr InBndr
expr@(Lam {}) cont :: SimplCont
cont
= {-#SCC "simplExprF1-Lam" #-}
SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam SimplEnv
env [InBndr]
zapped_bndrs Expr InBndr
body SimplCont
cont
where
(bndrs :: [InBndr]
bndrs, body :: Expr InBndr
body) = Expr InBndr -> ([InBndr], Expr InBndr)
forall b. Expr b -> ([b], Expr b)
collectBinders Expr InBndr
expr
zapped_bndrs :: [InBndr]
zapped_bndrs | Bool
need_to_zap = (InBndr -> InBndr) -> [InBndr] -> [InBndr]
forall a b. (a -> b) -> [a] -> [b]
map InBndr -> InBndr
zap [InBndr]
bndrs
| Bool
otherwise = [InBndr]
bndrs
need_to_zap :: Bool
need_to_zap = (InBndr -> Bool) -> [InBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any InBndr -> Bool
zappable_bndr (Int -> [InBndr] -> [InBndr]
forall a. Int -> [a] -> [a]
drop Int
n_args [InBndr]
bndrs)
n_args :: Int
n_args = SimplCont -> Int
countArgs SimplCont
cont
zappable_bndr :: InBndr -> Bool
zappable_bndr b :: InBndr
b = InBndr -> Bool
isId InBndr
b Bool -> Bool -> Bool
&& Bool -> Bool
not (InBndr -> Bool
isOneShotBndr InBndr
b)
zap :: InBndr -> InBndr
zap b :: InBndr
b | InBndr -> Bool
isTyVar InBndr
b = InBndr
b
| Bool
otherwise = InBndr -> InBndr
zapLamIdInfo InBndr
b
simplExprF1 env :: SimplEnv
env (Case scrut :: Expr InBndr
scrut bndr :: InBndr
bndr _ alts :: [Alt InBndr]
alts) cont :: SimplCont
cont
= {-#SCC "simplExprF1-Case" #-}
SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
scrut (Select :: DupFlag
-> InBndr -> [Alt InBndr] -> SimplEnv -> SimplCont -> SimplCont
Select { sc_dup :: DupFlag
sc_dup = DupFlag
NoDup, sc_bndr :: InBndr
sc_bndr = InBndr
bndr
, sc_alts :: [Alt InBndr]
sc_alts = [Alt InBndr]
alts
, sc_env :: SimplEnv
sc_env = SimplEnv
env, sc_cont :: SimplCont
sc_cont = SimplCont
cont })
simplExprF1 env :: SimplEnv
env (Let (Rec pairs :: [(InBndr, Expr InBndr)]
pairs) body :: Expr InBndr
body) cont :: SimplCont
cont
| Just pairs' :: [(InBndr, Expr InBndr)]
pairs' <- [(InBndr, Expr InBndr)] -> Maybe [(InBndr, Expr InBndr)]
joinPointBindings_maybe [(InBndr, Expr InBndr)]
pairs
= {-#SCC "simplRecJoinPoin" #-} SimplEnv
-> [(InBndr, Expr InBndr)]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplRecJoinPoint SimplEnv
env [(InBndr, Expr InBndr)]
pairs' Expr InBndr
body SimplCont
cont
| Bool
otherwise
= {-#SCC "simplRecE" #-} SimplEnv
-> [(InBndr, Expr InBndr)]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplRecE SimplEnv
env [(InBndr, Expr InBndr)]
pairs Expr InBndr
body SimplCont
cont
simplExprF1 env :: SimplEnv
env (Let (NonRec bndr :: InBndr
bndr rhs :: Expr InBndr
rhs) body :: Expr InBndr
body) cont :: SimplCont
cont
| Type ty :: OutType
ty <- Expr InBndr
rhs
= {-#SCC "simplExprF1-NonRecLet-Type" #-}
ASSERT( isTyVar bndr )
do { OutType
ty' <- SimplEnv -> OutType -> SimplM OutType
simplType SimplEnv
env OutType
ty
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF (SimplEnv -> InBndr -> OutType -> SimplEnv
extendTvSubst SimplEnv
env InBndr
bndr OutType
ty') Expr InBndr
body SimplCont
cont }
| Just (bndr' :: InBndr
bndr', rhs' :: Expr InBndr
rhs') <- InBndr -> Expr InBndr -> Maybe (InBndr, Expr InBndr)
joinPointBinding_maybe InBndr
bndr Expr InBndr
rhs
= {-#SCC "simplNonRecJoinPoint" #-} SimplEnv
-> InBndr
-> Expr InBndr
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplNonRecJoinPoint SimplEnv
env InBndr
bndr' Expr InBndr
rhs' Expr InBndr
body SimplCont
cont
| Bool
otherwise
= {-#SCC "simplNonRecE" #-} SimplEnv
-> InBndr
-> (Expr InBndr, SimplEnv)
-> ([InBndr], Expr InBndr)
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplNonRecE SimplEnv
env InBndr
bndr (Expr InBndr
rhs, SimplEnv
env) ([], Expr InBndr
body) SimplCont
cont
simplJoinRhs :: SimplEnv -> InId -> InExpr -> SimplCont
-> SimplM OutExpr
simplJoinRhs :: SimplEnv
-> InBndr -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplJoinRhs env :: SimplEnv
env bndr :: InBndr
bndr expr :: Expr InBndr
expr cont :: SimplCont
cont
| Just arity :: Int
arity <- InBndr -> Maybe Int
isJoinId_maybe InBndr
bndr
= do { let (join_bndrs :: [InBndr]
join_bndrs, join_body :: Expr InBndr
join_body) = Int -> Expr InBndr -> ([InBndr], Expr InBndr)
forall b. Int -> Expr b -> ([b], Expr b)
collectNBinders Int
arity Expr InBndr
expr
; (env' :: SimplEnv
env', join_bndrs' :: [InBndr]
join_bndrs') <- SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
simplLamBndrs SimplEnv
env [InBndr]
join_bndrs
; Expr InBndr
join_body' <- SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC SimplEnv
env' Expr InBndr
join_body SimplCont
cont
; Expr InBndr -> SimplM (Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr InBndr -> SimplM (Expr InBndr))
-> Expr InBndr -> SimplM (Expr InBndr)
forall a b. (a -> b) -> a -> b
$ [InBndr] -> Expr InBndr -> Expr InBndr
forall b. [b] -> Expr b -> Expr b
mkLams [InBndr]
join_bndrs' Expr InBndr
join_body' }
| Bool
otherwise
= [Char] -> SDoc -> SimplM (Expr InBndr)
forall a. HasCallStack => [Char] -> SDoc -> a
pprPanic "simplJoinRhs" (InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
bndr)
simplType :: SimplEnv -> InType -> SimplM OutType
simplType :: SimplEnv -> OutType -> SimplM OutType
simplType env :: SimplEnv
env ty :: OutType
ty
=
OutType -> ()
seqType OutType
new_ty () -> SimplM OutType -> SimplM OutType
forall a b. a -> b -> b
`seq` OutType -> SimplM OutType
forall (m :: * -> *) a. Monad m => a -> m a
return OutType
new_ty
where
new_ty :: OutType
new_ty = SimplEnv -> OutType -> OutType
substTy SimplEnv
env OutType
ty
simplCoercionF :: SimplEnv -> InCoercion -> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplCoercionF :: SimplEnv
-> Coercion -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplCoercionF env :: SimplEnv
env co :: Coercion
co cont :: SimplCont
cont
= do { Coercion
co' <- SimplEnv -> Coercion -> SimplM Coercion
simplCoercion SimplEnv
env Coercion
co
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (Coercion -> Expr InBndr
forall b. Coercion -> Expr b
Coercion Coercion
co') SimplCont
cont }
simplCoercion :: SimplEnv -> InCoercion -> SimplM OutCoercion
simplCoercion :: SimplEnv -> Coercion -> SimplM Coercion
simplCoercion env :: SimplEnv
env co :: Coercion
co
= do { DynFlags
dflags <- SimplM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; let opt_co :: Coercion
opt_co = DynFlags -> TCvSubst -> Coercion -> Coercion
optCoercion DynFlags
dflags (SimplEnv -> TCvSubst
getTCvSubst SimplEnv
env) Coercion
co
; Coercion -> ()
seqCo Coercion
opt_co () -> SimplM Coercion -> SimplM Coercion
forall a b. a -> b -> b
`seq` Coercion -> SimplM Coercion
forall (m :: * -> *) a. Monad m => a -> m a
return Coercion
opt_co }
simplTick :: SimplEnv -> Tickish Id -> InExpr -> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplTick :: SimplEnv
-> Tickish InBndr
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplTick env :: SimplEnv
env tickish :: Tickish InBndr
tickish expr :: Expr InBndr
expr cont :: SimplCont
cont
| Tickish InBndr
tickish Tickish InBndr -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
SoftScope
= do { (floats :: SimplFloats
floats, expr' :: Expr InBndr
expr') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
expr SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, Tickish InBndr -> Expr InBndr -> Expr InBndr
mkTick Tickish InBndr
tickish Expr InBndr
expr')
}
| Select {} <- SimplCont
cont, Just expr' :: Expr InBndr
expr' <- Maybe (Expr InBndr)
push_tick_inside
= SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
expr' SimplCont
cont
| Bool
otherwise
= SimplM (SimplFloats, Expr InBndr)
no_floating_past_tick
where
push_tick_inside :: Maybe (Expr InBndr)
push_tick_inside =
case Expr InBndr
expr0 of
Case scrut :: Expr InBndr
scrut bndr :: InBndr
bndr ty :: OutType
ty alts :: [Alt InBndr]
alts
-> Expr InBndr -> Maybe (Expr InBndr)
forall a. a -> Maybe a
Just (Expr InBndr -> Maybe (Expr InBndr))
-> Expr InBndr -> Maybe (Expr InBndr)
forall a b. (a -> b) -> a -> b
$ Expr InBndr -> InBndr -> OutType -> [Alt InBndr] -> Expr InBndr
forall b. Expr b -> b -> OutType -> [Alt b] -> Expr b
Case (Expr InBndr -> Expr InBndr
tickScrut Expr InBndr
scrut) InBndr
bndr OutType
ty ((Alt InBndr -> Alt InBndr) -> [Alt InBndr] -> [Alt InBndr]
forall a b. (a -> b) -> [a] -> [b]
map Alt InBndr -> Alt InBndr
forall a b. (a, b, Expr InBndr) -> (a, b, Expr InBndr)
tickAlt [Alt InBndr]
alts)
_other :: Expr InBndr
_other -> Maybe (Expr InBndr)
forall a. Maybe a
Nothing
where (ticks :: [Tickish InBndr]
ticks, expr0 :: Expr InBndr
expr0) = (Tickish InBndr -> Bool)
-> Expr InBndr -> ([Tickish InBndr], Expr InBndr)
forall b.
(Tickish InBndr -> Bool) -> Expr b -> ([Tickish InBndr], Expr b)
stripTicksTop Tickish InBndr -> Bool
forall id. Tickish id -> Bool
movable (Tickish InBndr -> Expr InBndr -> Expr InBndr
forall b. Tickish InBndr -> Expr b -> Expr b
Tick Tickish InBndr
tickish Expr InBndr
expr)
movable :: Tickish id -> Bool
movable t :: Tickish id
t = Bool -> Bool
not (Tickish id -> Bool
forall id. Tickish id -> Bool
tickishCounts Tickish id
t) Bool -> Bool -> Bool
||
Tickish id
t Tickish id -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
NoScope Bool -> Bool -> Bool
||
Tickish id -> Bool
forall id. Tickish id -> Bool
tickishCanSplit Tickish id
t
tickScrut :: Expr InBndr -> Expr InBndr
tickScrut e :: Expr InBndr
e = (Tickish InBndr -> Expr InBndr -> Expr InBndr)
-> Expr InBndr -> [Tickish InBndr] -> Expr InBndr
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Tickish InBndr -> Expr InBndr -> Expr InBndr
mkTick Expr InBndr
e [Tickish InBndr]
ticks
tickAlt :: (a, b, Expr InBndr) -> (a, b, Expr InBndr)
tickAlt (c :: a
c,bs :: b
bs,e :: Expr InBndr
e) = (a
c,b
bs, (Tickish InBndr -> Expr InBndr -> Expr InBndr)
-> Expr InBndr -> [Tickish InBndr] -> Expr InBndr
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Tickish InBndr -> Expr InBndr -> Expr InBndr
mkTick Expr InBndr
e [Tickish InBndr]
ts_scope)
ts_scope :: [Tickish InBndr]
ts_scope = (Tickish InBndr -> Tickish InBndr)
-> [Tickish InBndr] -> [Tickish InBndr]
forall a b. (a -> b) -> [a] -> [b]
map Tickish InBndr -> Tickish InBndr
forall id. Tickish id -> Tickish id
mkNoCount ([Tickish InBndr] -> [Tickish InBndr])
-> [Tickish InBndr] -> [Tickish InBndr]
forall a b. (a -> b) -> a -> b
$
(Tickish InBndr -> Bool) -> [Tickish InBndr] -> [Tickish InBndr]
forall a. (a -> Bool) -> [a] -> [a]
filter (Bool -> Bool
not (Bool -> Bool)
-> (Tickish InBndr -> Bool) -> Tickish InBndr -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Tickish InBndr -> TickishScoping -> Bool
forall id. Tickish id -> TickishScoping -> Bool
`tickishScopesLike` TickishScoping
NoScope)) [Tickish InBndr]
ticks
no_floating_past_tick :: SimplM (SimplFloats, Expr InBndr)
no_floating_past_tick =
do { let (inc :: SimplCont
inc,outc :: SimplCont
outc) = SimplCont -> (SimplCont, SimplCont)
splitCont SimplCont
cont
; (floats :: SimplFloats
floats, expr1 :: Expr InBndr
expr1) <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
expr SimplCont
inc
; let expr2 :: Expr InBndr
expr2 = SimplFloats -> Expr InBndr -> Expr InBndr
wrapFloats SimplFloats
floats Expr InBndr
expr1
tickish' :: Tickish InBndr
tickish' = SimplEnv -> Tickish InBndr -> Tickish InBndr
simplTickish SimplEnv
env Tickish InBndr
tickish
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (Tickish InBndr -> Expr InBndr -> Expr InBndr
mkTick Tickish InBndr
tickish' Expr InBndr
expr2) SimplCont
outc
}
simplTickish :: SimplEnv -> Tickish InBndr -> Tickish InBndr
simplTickish env :: SimplEnv
env tickish :: Tickish InBndr
tickish
| Breakpoint n :: Int
n ids :: [InBndr]
ids <- Tickish InBndr
tickish
= Int -> [InBndr] -> Tickish InBndr
forall id. Int -> [id] -> Tickish id
Breakpoint Int
n ((InBndr -> InBndr) -> [InBndr] -> [InBndr]
forall a b. (a -> b) -> [a] -> [b]
map (SimplSR -> InBndr
getDoneId (SimplSR -> InBndr) -> (InBndr -> SimplSR) -> InBndr -> InBndr
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SimplEnv -> InBndr -> SimplSR
substId SimplEnv
env) [InBndr]
ids)
| Bool
otherwise = Tickish InBndr
tickish
splitCont :: SimplCont -> (SimplCont, SimplCont)
splitCont :: SimplCont -> (SimplCont, SimplCont)
splitCont cont :: SimplCont
cont@(ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
tail }) = (SimplCont
cont { sc_cont :: SimplCont
sc_cont = SimplCont
inc }, SimplCont
outc)
where (inc :: SimplCont
inc,outc :: SimplCont
outc) = SimplCont -> (SimplCont, SimplCont)
splitCont SimplCont
tail
splitCont (CastIt co :: Coercion
co c :: SimplCont
c) = (Coercion -> SimplCont -> SimplCont
CastIt Coercion
co SimplCont
inc, SimplCont
outc)
where (inc :: SimplCont
inc,outc :: SimplCont
outc) = SimplCont -> (SimplCont, SimplCont)
splitCont SimplCont
c
splitCont other :: SimplCont
other = (OutType -> SimplCont
mkBoringStop (SimplCont -> OutType
contHoleType SimplCont
other), SimplCont
other)
getDoneId :: SimplSR -> InBndr
getDoneId (DoneId id :: InBndr
id) = InBndr
id
getDoneId (DoneEx e :: Expr InBndr
e _) = HasDebugCallStack => Expr InBndr -> InBndr
Expr InBndr -> InBndr
getIdFromTrivialExpr Expr InBndr
e
getDoneId other :: SimplSR
other = [Char] -> SDoc -> InBndr
forall a. HasCallStack => [Char] -> SDoc -> a
pprPanic "getDoneId" (SimplSR -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplSR
other)
rebuild :: SimplEnv -> OutExpr -> SimplCont -> SimplM (SimplFloats, OutExpr)
rebuild :: SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild env :: SimplEnv
env expr :: Expr InBndr
expr cont :: SimplCont
cont
= case SimplCont
cont of
Stop {} -> (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, Expr InBndr
expr)
TickIt t :: Tickish InBndr
t cont :: SimplCont
cont -> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (Tickish InBndr -> Expr InBndr -> Expr InBndr
mkTick Tickish InBndr
t Expr InBndr
expr) SimplCont
cont
CastIt co :: Coercion
co cont :: SimplCont
cont -> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (Expr InBndr -> Coercion -> Expr InBndr
mkCast Expr InBndr
expr Coercion
co) SimplCont
cont
Select { sc_bndr :: SimplCont -> InBndr
sc_bndr = InBndr
bndr, sc_alts :: SimplCont -> [Alt InBndr]
sc_alts = [Alt InBndr]
alts, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont }
-> SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
rebuildCase (SimplEnv
se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env) Expr InBndr
expr InBndr
bndr [Alt InBndr]
alts SimplCont
cont
StrictArg { sc_fun :: SimplCont -> ArgInfo
sc_fun = ArgInfo
fun, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont }
-> SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall SimplEnv
env (ArgInfo
fun ArgInfo -> Expr InBndr -> ArgInfo
`addValArgTo` Expr InBndr
expr) SimplCont
cont
StrictBind { sc_bndr :: SimplCont -> InBndr
sc_bndr = InBndr
b, sc_bndrs :: SimplCont -> [InBndr]
sc_bndrs = [InBndr]
bs, sc_body :: SimplCont -> Expr InBndr
sc_body = Expr InBndr
body
, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont }
-> do { (floats1 :: SimplFloats
floats1, env' :: SimplEnv
env') <- SimplEnv -> InBndr -> Expr InBndr -> SimplM (SimplFloats, SimplEnv)
simplNonRecX (SimplEnv
se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env) InBndr
b Expr InBndr
expr
; (floats2 :: SimplFloats
floats2, expr' :: Expr InBndr
expr') <- SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam SimplEnv
env' [InBndr]
bs Expr InBndr
body SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
expr') }
ApplyToTy { sc_arg_ty :: SimplCont -> OutType
sc_arg_ty = OutType
ty, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont}
-> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (Expr InBndr -> Expr InBndr -> Expr InBndr
forall b. Expr b -> Expr b -> Expr b
App Expr InBndr
expr (OutType -> Expr InBndr
forall b. OutType -> Expr b
Type OutType
ty)) SimplCont
cont
ApplyToVal { sc_arg :: SimplCont -> Expr InBndr
sc_arg = Expr InBndr
arg, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
se, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup_flag, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont}
-> do { (_, _, arg' :: Expr InBndr
arg') <- SimplEnv
-> DupFlag
-> SimplEnv
-> Expr InBndr
-> SimplM (DupFlag, SimplEnv, Expr InBndr)
simplArg SimplEnv
env DupFlag
dup_flag SimplEnv
se Expr InBndr
arg
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (Expr InBndr -> Expr InBndr -> Expr InBndr
forall b. Expr b -> Expr b -> Expr b
App Expr InBndr
expr Expr InBndr
arg') SimplCont
cont }
simplCast :: SimplEnv -> InExpr -> Coercion -> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplCast :: SimplEnv
-> Expr InBndr
-> Coercion
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplCast env :: SimplEnv
env body :: Expr InBndr
body co0 :: Coercion
co0 cont0 :: SimplCont
cont0
= do { Coercion
co1 <- {-#SCC "simplCast-simplCoercion" #-} SimplEnv -> Coercion -> SimplM Coercion
simplCoercion SimplEnv
env Coercion
co0
; SimplCont
cont1 <- {-#SCC "simplCast-addCoerce" #-}
if Coercion -> Bool
isReflCo Coercion
co1
then SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return SimplCont
cont0
else Coercion -> SimplCont -> SimplM SimplCont
addCoerce Coercion
co1 SimplCont
cont0
; {-#SCC "simplCast-simplExprF" #-} SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
body SimplCont
cont1 }
where
addCoerceM :: MOutCoercion -> SimplCont -> SimplM SimplCont
addCoerceM :: MOutCoercion -> SimplCont -> SimplM SimplCont
addCoerceM MRefl cont :: SimplCont
cont = SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return SimplCont
cont
addCoerceM (MCo co :: Coercion
co) cont :: SimplCont
cont = Coercion -> SimplCont -> SimplM SimplCont
addCoerce Coercion
co SimplCont
cont
addCoerce :: OutCoercion -> SimplCont -> SimplM SimplCont
addCoerce :: Coercion -> SimplCont -> SimplM SimplCont
addCoerce co1 :: Coercion
co1 (CastIt co2 :: Coercion
co2 cont :: SimplCont
cont)
| Coercion -> Bool
isReflexiveCo Coercion
co' = SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return SimplCont
cont
| Bool
otherwise = Coercion -> SimplCont -> SimplM SimplCont
addCoerce Coercion
co' SimplCont
cont
where
co' :: Coercion
co' = Coercion -> Coercion -> Coercion
mkTransCo Coercion
co1 Coercion
co2
addCoerce co :: Coercion
co cont :: SimplCont
cont@(ApplyToTy { sc_arg_ty :: SimplCont -> OutType
sc_arg_ty = OutType
arg_ty, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
tail })
| Just (arg_ty' :: OutType
arg_ty', m_co' :: MOutCoercion
m_co') <- Coercion -> OutType -> Maybe (OutType, MOutCoercion)
pushCoTyArg Coercion
co OutType
arg_ty
, Pair hole_ty :: OutType
hole_ty _ <- Coercion -> Pair OutType
coercionKind Coercion
co
= {-#SCC "addCoerce-pushCoTyArg" #-}
do { SimplCont
tail' <- MOutCoercion -> SimplCont -> SimplM SimplCont
addCoerceM MOutCoercion
m_co' SimplCont
tail
; SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplCont
cont { sc_arg_ty :: OutType
sc_arg_ty = OutType
arg_ty'
, sc_hole_ty :: OutType
sc_hole_ty = OutType
hole_ty
, sc_cont :: SimplCont
sc_cont = SimplCont
tail' }) }
addCoerce co :: Coercion
co cont :: SimplCont
cont@(ApplyToVal { sc_arg :: SimplCont -> Expr InBndr
sc_arg = Expr InBndr
arg, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
arg_se
, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
tail })
| Just (co1 :: Coercion
co1, m_co2 :: MOutCoercion
m_co2) <- Coercion -> Maybe (Coercion, MOutCoercion)
pushCoValArg Coercion
co
, Pair _ new_ty :: OutType
new_ty <- Coercion -> Pair OutType
coercionKind Coercion
co1
, Bool -> Bool
not (OutType -> Bool
isTypeLevPoly OutType
new_ty)
= {-#SCC "addCoerce-pushCoValArg" #-}
do { SimplCont
tail' <- MOutCoercion -> SimplCont -> SimplM SimplCont
addCoerceM MOutCoercion
m_co2 SimplCont
tail
; if Coercion -> Bool
isReflCo Coercion
co1
then SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplCont
cont { sc_cont :: SimplCont
sc_cont = SimplCont
tail' })
else do
{ (dup' :: DupFlag
dup', arg_se' :: SimplEnv
arg_se', arg' :: Expr InBndr
arg') <- SimplEnv
-> DupFlag
-> SimplEnv
-> Expr InBndr
-> SimplM (DupFlag, SimplEnv, Expr InBndr)
simplArg SimplEnv
env DupFlag
dup SimplEnv
arg_se Expr InBndr
arg
; SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return (ApplyToVal :: DupFlag -> Expr InBndr -> SimplEnv -> SimplCont -> SimplCont
ApplyToVal { sc_arg :: Expr InBndr
sc_arg = Expr InBndr -> Coercion -> Expr InBndr
mkCast Expr InBndr
arg' Coercion
co1
, sc_env :: SimplEnv
sc_env = SimplEnv
arg_se'
, sc_dup :: DupFlag
sc_dup = DupFlag
dup'
, sc_cont :: SimplCont
sc_cont = SimplCont
tail' }) } }
addCoerce co :: Coercion
co cont :: SimplCont
cont
| Coercion -> Bool
isReflexiveCo Coercion
co = SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return SimplCont
cont
| Bool
otherwise = SimplCont -> SimplM SimplCont
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> SimplCont -> SimplCont
CastIt Coercion
co SimplCont
cont)
simplArg :: SimplEnv -> DupFlag -> StaticEnv -> CoreExpr
-> SimplM (DupFlag, StaticEnv, OutExpr)
simplArg :: SimplEnv
-> DupFlag
-> SimplEnv
-> Expr InBndr
-> SimplM (DupFlag, SimplEnv, Expr InBndr)
simplArg env :: SimplEnv
env dup_flag :: DupFlag
dup_flag arg_env :: SimplEnv
arg_env arg :: Expr InBndr
arg
| DupFlag -> Bool
isSimplified DupFlag
dup_flag
= (DupFlag, SimplEnv, Expr InBndr)
-> SimplM (DupFlag, SimplEnv, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (DupFlag
dup_flag, SimplEnv
arg_env, Expr InBndr
arg)
| Bool
otherwise
= do { Expr InBndr
arg' <- SimplEnv -> Expr InBndr -> SimplM (Expr InBndr)
simplExpr (SimplEnv
arg_env SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env) Expr InBndr
arg
; (DupFlag, SimplEnv, Expr InBndr)
-> SimplM (DupFlag, SimplEnv, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (DupFlag
Simplified, SimplEnv -> SimplEnv
zapSubstEnv SimplEnv
arg_env, Expr InBndr
arg') }
simplLam :: SimplEnv -> [InId] -> InExpr -> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplLam :: SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam env :: SimplEnv
env [] body :: Expr InBndr
body cont :: SimplCont
cont
= SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
body SimplCont
cont
simplLam env :: SimplEnv
env (bndr :: InBndr
bndr:bndrs :: [InBndr]
bndrs) body :: Expr InBndr
body (ApplyToTy { sc_arg_ty :: SimplCont -> OutType
sc_arg_ty = OutType
arg_ty, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= do { Tick -> SimplM ()
tick (InBndr -> Tick
BetaReduction InBndr
bndr)
; SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam (SimplEnv -> InBndr -> OutType -> SimplEnv
extendTvSubst SimplEnv
env InBndr
bndr OutType
arg_ty) [InBndr]
bndrs Expr InBndr
body SimplCont
cont }
simplLam env :: SimplEnv
env (bndr :: InBndr
bndr:bndrs :: [InBndr]
bndrs) body :: Expr InBndr
body (ApplyToVal { sc_arg :: SimplCont -> Expr InBndr
sc_arg = Expr InBndr
arg, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
arg_se
, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup })
| DupFlag -> Bool
isSimplified DupFlag
dup
= do { Tick -> SimplM ()
tick (InBndr -> Tick
BetaReduction InBndr
bndr)
; (floats1 :: SimplFloats
floats1, env' :: SimplEnv
env') <- SimplEnv -> InBndr -> Expr InBndr -> SimplM (SimplFloats, SimplEnv)
simplNonRecX SimplEnv
env InBndr
zapped_bndr Expr InBndr
arg
; (floats2 :: SimplFloats
floats2, expr' :: Expr InBndr
expr') <- SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam SimplEnv
env' [InBndr]
bndrs Expr InBndr
body SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
expr') }
| Bool
otherwise
= do { Tick -> SimplM ()
tick (InBndr -> Tick
BetaReduction InBndr
bndr)
; SimplEnv
-> InBndr
-> (Expr InBndr, SimplEnv)
-> ([InBndr], Expr InBndr)
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplNonRecE SimplEnv
env InBndr
zapped_bndr (Expr InBndr
arg, SimplEnv
arg_se) ([InBndr]
bndrs, Expr InBndr
body) SimplCont
cont }
where
zapped_bndr :: InBndr
zapped_bndr
| InBndr -> Bool
isId InBndr
bndr = InBndr -> InBndr
zapStableUnfolding InBndr
bndr
| Bool
otherwise = InBndr
bndr
simplLam env :: SimplEnv
env bndrs :: [InBndr]
bndrs body :: Expr InBndr
body (TickIt tickish :: Tickish InBndr
tickish cont :: SimplCont
cont)
| Bool -> Bool
not (Tickish InBndr -> Bool
forall id. Tickish id -> Bool
tickishCounts Tickish InBndr
tickish)
= SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam SimplEnv
env [InBndr]
bndrs Expr InBndr
body SimplCont
cont
simplLam env :: SimplEnv
env bndrs :: [InBndr]
bndrs body :: Expr InBndr
body cont :: SimplCont
cont
= do { (env' :: SimplEnv
env', bndrs' :: [InBndr]
bndrs') <- SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
simplLamBndrs SimplEnv
env [InBndr]
bndrs
; Expr InBndr
body' <- SimplEnv -> Expr InBndr -> SimplM (Expr InBndr)
simplExpr SimplEnv
env' Expr InBndr
body
; Expr InBndr
new_lam <- SimplEnv
-> [InBndr] -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
mkLam SimplEnv
env [InBndr]
bndrs' Expr InBndr
body' SimplCont
cont
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env' Expr InBndr
new_lam SimplCont
cont }
simplLamBndr :: SimplEnv -> InBndr -> SimplM (SimplEnv, OutBndr)
simplLamBndr :: SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplLamBndr env :: SimplEnv
env bndr :: InBndr
bndr
| InBndr -> Bool
isId InBndr
bndr Bool -> Bool -> Bool
&& Unfolding -> Bool
isFragileUnfolding Unfolding
old_unf
= do { (env1 :: SimplEnv
env1, bndr1 :: InBndr
bndr1) <- SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplBinder SimplEnv
env InBndr
bndr
; Unfolding
unf' <- SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> Unfolding
-> OutType
-> SimplM Unfolding
simplStableUnfolding SimplEnv
env1 TopLevelFlag
NotTopLevel MaybeJoinCont
forall a. Maybe a
Nothing InBndr
bndr
Unfolding
old_unf (InBndr -> OutType
idType InBndr
bndr1)
; let bndr2 :: InBndr
bndr2 = InBndr
bndr1 InBndr -> Unfolding -> InBndr
`setIdUnfolding` Unfolding
unf'
; (SimplEnv, InBndr) -> SimplM (SimplEnv, InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> InBndr -> SimplEnv
modifyInScope SimplEnv
env1 InBndr
bndr2, InBndr
bndr2) }
| Bool
otherwise
= SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplBinder SimplEnv
env InBndr
bndr
where
old_unf :: Unfolding
old_unf = InBndr -> Unfolding
idUnfolding InBndr
bndr
simplLamBndrs :: SimplEnv -> [InBndr] -> SimplM (SimplEnv, [OutBndr])
simplLamBndrs :: SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
simplLamBndrs env :: SimplEnv
env bndrs :: [InBndr]
bndrs = (SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr))
-> SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
forall (m :: * -> *) acc x y.
Monad m =>
(acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
mapAccumLM SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplLamBndr SimplEnv
env [InBndr]
bndrs
simplNonRecE :: SimplEnv
-> InId
-> (InExpr, SimplEnv)
-> ([InBndr], InExpr)
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplNonRecE :: SimplEnv
-> InBndr
-> (Expr InBndr, SimplEnv)
-> ([InBndr], Expr InBndr)
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplNonRecE env :: SimplEnv
env bndr :: InBndr
bndr (rhs :: Expr InBndr
rhs, rhs_se :: SimplEnv
rhs_se) (bndrs :: [InBndr]
bndrs, body :: Expr InBndr
body) cont :: SimplCont
cont
| ASSERT( isId bndr && not (isJoinId bndr) ) True
, Just env' :: SimplEnv
env' <- SimplEnv
-> TopLevelFlag
-> InBndr
-> Expr InBndr
-> SimplEnv
-> Maybe SimplEnv
preInlineUnconditionally SimplEnv
env TopLevelFlag
NotTopLevel InBndr
bndr Expr InBndr
rhs SimplEnv
rhs_se
= do { Tick -> SimplM ()
tick (InBndr -> Tick
PreInlineUnconditionally InBndr
bndr)
;
SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam SimplEnv
env' [InBndr]
bndrs Expr InBndr
body SimplCont
cont }
| InBndr -> Bool
isStrictId InBndr
bndr
, SimplMode -> Bool
sm_case_case (SimplEnv -> SimplMode
getMode SimplEnv
env)
= SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF (SimplEnv
rhs_se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env) Expr InBndr
rhs
(StrictBind :: DupFlag
-> InBndr
-> [InBndr]
-> Expr InBndr
-> SimplEnv
-> SimplCont
-> SimplCont
StrictBind { sc_bndr :: InBndr
sc_bndr = InBndr
bndr, sc_bndrs :: [InBndr]
sc_bndrs = [InBndr]
bndrs, sc_body :: Expr InBndr
sc_body = Expr InBndr
body
, sc_env :: SimplEnv
sc_env = SimplEnv
env, sc_cont :: SimplCont
sc_cont = SimplCont
cont, sc_dup :: DupFlag
sc_dup = DupFlag
NoDup })
| Bool
otherwise
= ASSERT( not (isTyVar bndr) )
do { (env1 :: SimplEnv
env1, bndr1 :: InBndr
bndr1) <- SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplNonRecBndr SimplEnv
env InBndr
bndr
; (env2 :: SimplEnv
env2, bndr2 :: InBndr
bndr2) <- SimplEnv
-> InBndr -> InBndr -> MaybeJoinCont -> SimplM (SimplEnv, InBndr)
addBndrRules SimplEnv
env1 InBndr
bndr InBndr
bndr1 MaybeJoinCont
forall a. Maybe a
Nothing
; (floats1 :: SimplFloats
floats1, env3 :: SimplEnv
env3) <- SimplEnv
-> TopLevelFlag
-> RecFlag
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplLazyBind SimplEnv
env2 TopLevelFlag
NotTopLevel RecFlag
NonRecursive InBndr
bndr InBndr
bndr2 Expr InBndr
rhs SimplEnv
rhs_se
; (floats2 :: SimplFloats
floats2, expr' :: Expr InBndr
expr') <- SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam SimplEnv
env3 [InBndr]
bndrs Expr InBndr
body SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
expr') }
simplRecE :: SimplEnv
-> [(InId, InExpr)]
-> InExpr
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplRecE :: SimplEnv
-> [(InBndr, Expr InBndr)]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplRecE env :: SimplEnv
env pairs :: [(InBndr, Expr InBndr)]
pairs body :: Expr InBndr
body cont :: SimplCont
cont
= do { let bndrs :: [InBndr]
bndrs = ((InBndr, Expr InBndr) -> InBndr)
-> [(InBndr, Expr InBndr)] -> [InBndr]
forall a b. (a -> b) -> [a] -> [b]
map (InBndr, Expr InBndr) -> InBndr
forall a b. (a, b) -> a
fst [(InBndr, Expr InBndr)]
pairs
; MASSERT(all (not . isJoinId) bndrs)
; SimplEnv
env1 <- SimplEnv -> [InBndr] -> SimplM SimplEnv
simplRecBndrs SimplEnv
env [InBndr]
bndrs
; (floats1 :: SimplFloats
floats1, env2 :: SimplEnv
env2) <- SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> [(InBndr, Expr InBndr)]
-> SimplM (SimplFloats, SimplEnv)
simplRecBind SimplEnv
env1 TopLevelFlag
NotTopLevel MaybeJoinCont
forall a. Maybe a
Nothing [(InBndr, Expr InBndr)]
pairs
; (floats2 :: SimplFloats
floats2, expr' :: Expr InBndr
expr') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env2 Expr InBndr
body SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
expr') }
type MaybeJoinCont = Maybe SimplCont
simplNonRecJoinPoint :: SimplEnv -> InId -> InExpr
-> InExpr -> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplNonRecJoinPoint :: SimplEnv
-> InBndr
-> Expr InBndr
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplNonRecJoinPoint env :: SimplEnv
env bndr :: InBndr
bndr rhs :: Expr InBndr
rhs body :: Expr InBndr
body cont :: SimplCont
cont
| ASSERT( isJoinId bndr ) True
, Just env' :: SimplEnv
env' <- SimplEnv
-> TopLevelFlag
-> InBndr
-> Expr InBndr
-> SimplEnv
-> Maybe SimplEnv
preInlineUnconditionally SimplEnv
env TopLevelFlag
NotTopLevel InBndr
bndr Expr InBndr
rhs SimplEnv
env
= do { Tick -> SimplM ()
tick (InBndr -> Tick
PreInlineUnconditionally InBndr
bndr)
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env' Expr InBndr
body SimplCont
cont }
| Bool
otherwise
= SimplEnv
-> SimplCont
-> (SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplM (SimplFloats, Expr InBndr)
wrapJoinCont SimplEnv
env SimplCont
cont ((SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplM (SimplFloats, Expr InBndr))
-> (SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplM (SimplFloats, Expr InBndr)
forall a b. (a -> b) -> a -> b
$ \ env :: SimplEnv
env cont :: SimplCont
cont ->
do {
; let res_ty :: OutType
res_ty = SimplCont -> OutType
contResultType SimplCont
cont
; (env1 :: SimplEnv
env1, bndr1 :: InBndr
bndr1) <- SimplEnv -> OutType -> InBndr -> SimplM (SimplEnv, InBndr)
simplNonRecJoinBndr SimplEnv
env OutType
res_ty InBndr
bndr
; (env2 :: SimplEnv
env2, bndr2 :: InBndr
bndr2) <- SimplEnv
-> InBndr -> InBndr -> MaybeJoinCont -> SimplM (SimplEnv, InBndr)
addBndrRules SimplEnv
env1 InBndr
bndr InBndr
bndr1 (SimplCont -> MaybeJoinCont
forall a. a -> Maybe a
Just SimplCont
cont)
; (floats1 :: SimplFloats
floats1, env3 :: SimplEnv
env3) <- SimplEnv
-> SimplCont
-> InBndr
-> InBndr
-> Expr InBndr
-> SimplEnv
-> SimplM (SimplFloats, SimplEnv)
simplJoinBind SimplEnv
env2 SimplCont
cont InBndr
bndr InBndr
bndr2 Expr InBndr
rhs SimplEnv
env
; (floats2 :: SimplFloats
floats2, body' :: Expr InBndr
body') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env3 Expr InBndr
body SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
body') }
simplRecJoinPoint :: SimplEnv -> [(InId, InExpr)]
-> InExpr -> SimplCont
-> SimplM (SimplFloats, OutExpr)
simplRecJoinPoint :: SimplEnv
-> [(InBndr, Expr InBndr)]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplRecJoinPoint env :: SimplEnv
env pairs :: [(InBndr, Expr InBndr)]
pairs body :: Expr InBndr
body cont :: SimplCont
cont
= SimplEnv
-> SimplCont
-> (SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplM (SimplFloats, Expr InBndr)
wrapJoinCont SimplEnv
env SimplCont
cont ((SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplM (SimplFloats, Expr InBndr))
-> (SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplM (SimplFloats, Expr InBndr)
forall a b. (a -> b) -> a -> b
$ \ env :: SimplEnv
env cont :: SimplCont
cont ->
do { let bndrs :: [InBndr]
bndrs = ((InBndr, Expr InBndr) -> InBndr)
-> [(InBndr, Expr InBndr)] -> [InBndr]
forall a b. (a -> b) -> [a] -> [b]
map (InBndr, Expr InBndr) -> InBndr
forall a b. (a, b) -> a
fst [(InBndr, Expr InBndr)]
pairs
res_ty :: OutType
res_ty = SimplCont -> OutType
contResultType SimplCont
cont
; SimplEnv
env1 <- SimplEnv -> OutType -> [InBndr] -> SimplM SimplEnv
simplRecJoinBndrs SimplEnv
env OutType
res_ty [InBndr]
bndrs
; (floats1 :: SimplFloats
floats1, env2 :: SimplEnv
env2) <- SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> [(InBndr, Expr InBndr)]
-> SimplM (SimplFloats, SimplEnv)
simplRecBind SimplEnv
env1 TopLevelFlag
NotTopLevel (SimplCont -> MaybeJoinCont
forall a. a -> Maybe a
Just SimplCont
cont) [(InBndr, Expr InBndr)]
pairs
; (floats2 :: SimplFloats
floats2, body' :: Expr InBndr
body') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env2 Expr InBndr
body SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
body') }
wrapJoinCont :: SimplEnv -> SimplCont
-> (SimplEnv -> SimplCont -> SimplM (SimplFloats, OutExpr))
-> SimplM (SimplFloats, OutExpr)
wrapJoinCont :: SimplEnv
-> SimplCont
-> (SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr))
-> SimplM (SimplFloats, Expr InBndr)
wrapJoinCont env :: SimplEnv
env cont :: SimplCont
cont thing_inside :: SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
thing_inside
| SimplCont -> Bool
contIsStop SimplCont
cont
= SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
thing_inside SimplEnv
env SimplCont
cont
| Bool -> Bool
not (SimplMode -> Bool
sm_case_case (SimplEnv -> SimplMode
getMode SimplEnv
env))
= do { (floats1 :: SimplFloats
floats1, expr1 :: Expr InBndr
expr1) <- SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
thing_inside SimplEnv
env (OutType -> SimplCont
mkBoringStop (SimplCont -> OutType
contHoleType SimplCont
cont))
; let (floats2 :: SimplFloats
floats2, expr2 :: Expr InBndr
expr2) = SimplFloats -> Expr InBndr -> (SimplFloats, Expr InBndr)
wrapJoinFloatsX SimplFloats
floats1 Expr InBndr
expr1
; (floats3 :: SimplFloats
floats3, expr3 :: Expr InBndr
expr3) <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild (SimplEnv
env SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
floats2) Expr InBndr
expr2 SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats2 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats3, Expr InBndr
expr3) }
| Bool
otherwise
= do { (floats1 :: SimplFloats
floats1, cont' :: SimplCont
cont') <- SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont SimplEnv
env SimplCont
cont
; (floats2 :: SimplFloats
floats2, result :: Expr InBndr
result) <- SimplEnv -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
thing_inside (SimplEnv
env SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
floats1) SimplCont
cont'
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
result) }
trimJoinCont :: Id -> Maybe JoinArity -> SimplCont -> SimplCont
trimJoinCont :: InBndr -> Maybe Int -> SimplCont -> SimplCont
trimJoinCont _ Nothing cont :: SimplCont
cont
= SimplCont
cont
trimJoinCont var :: InBndr
var (Just arity :: Int
arity) cont :: SimplCont
cont
= Int -> SimplCont -> SimplCont
forall a. (Eq a, Num a) => a -> SimplCont -> SimplCont
trim Int
arity SimplCont
cont
where
trim :: a -> SimplCont -> SimplCont
trim 0 cont :: SimplCont
cont@(Stop {})
= SimplCont
cont
trim 0 cont :: SimplCont
cont
= OutType -> SimplCont
mkBoringStop (SimplCont -> OutType
contResultType SimplCont
cont)
trim n :: a
n cont :: SimplCont
cont@(ApplyToVal { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= SimplCont
cont { sc_cont :: SimplCont
sc_cont = a -> SimplCont -> SimplCont
trim (a
na -> a -> a
forall a. Num a => a -> a -> a
-1) SimplCont
k }
trim n :: a
n cont :: SimplCont
cont@(ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
k })
= SimplCont
cont { sc_cont :: SimplCont
sc_cont = a -> SimplCont -> SimplCont
trim (a
na -> a -> a
forall a. Num a => a -> a -> a
-1) SimplCont
k }
trim _ cont :: SimplCont
cont
= [Char] -> SDoc -> SimplCont
forall a. HasCallStack => [Char] -> SDoc -> a
pprPanic "completeCall" (SDoc -> SimplCont) -> SDoc -> SimplCont
forall a b. (a -> b) -> a -> b
$ InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
var SDoc -> SDoc -> SDoc
$$ SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
cont
simplVar :: SimplEnv -> InVar -> SimplM OutExpr
simplVar :: SimplEnv -> InBndr -> SimplM (Expr InBndr)
simplVar env :: SimplEnv
env var :: InBndr
var
| InBndr -> Bool
isTyVar InBndr
var = Expr InBndr -> SimplM (Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (OutType -> Expr InBndr
forall b. OutType -> Expr b
Type (SimplEnv -> InBndr -> OutType
substTyVar SimplEnv
env InBndr
var))
| InBndr -> Bool
isCoVar InBndr
var = Expr InBndr -> SimplM (Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> Expr InBndr
forall b. Coercion -> Expr b
Coercion (SimplEnv -> InBndr -> Coercion
substCoVar SimplEnv
env InBndr
var))
| Bool
otherwise
= case SimplEnv -> InBndr -> SimplSR
substId SimplEnv
env InBndr
var of
ContEx tvs :: TvSubstEnv
tvs cvs :: CvSubstEnv
cvs ids :: SimplIdSubst
ids e :: Expr InBndr
e -> SimplEnv -> Expr InBndr -> SimplM (Expr InBndr)
simplExpr (SimplEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> SimplEnv
setSubstEnv SimplEnv
env TvSubstEnv
tvs CvSubstEnv
cvs SimplIdSubst
ids) Expr InBndr
e
DoneId var1 :: InBndr
var1 -> Expr InBndr -> SimplM (Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (InBndr -> Expr InBndr
forall b. InBndr -> Expr b
Var InBndr
var1)
DoneEx e :: Expr InBndr
e _ -> Expr InBndr -> SimplM (Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return Expr InBndr
e
simplIdF :: SimplEnv -> InId -> SimplCont -> SimplM (SimplFloats, OutExpr)
simplIdF :: SimplEnv
-> InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplIdF env :: SimplEnv
env var :: InBndr
var cont :: SimplCont
cont
= case SimplEnv -> InBndr -> SimplSR
substId SimplEnv
env InBndr
var of
ContEx tvs :: TvSubstEnv
tvs cvs :: CvSubstEnv
cvs ids :: SimplIdSubst
ids e :: Expr InBndr
e -> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF (SimplEnv -> TvSubstEnv -> CvSubstEnv -> SimplIdSubst -> SimplEnv
setSubstEnv SimplEnv
env TvSubstEnv
tvs CvSubstEnv
cvs SimplIdSubst
ids) Expr InBndr
e SimplCont
cont
DoneId var1 :: InBndr
var1 -> SimplEnv
-> InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
completeCall SimplEnv
env InBndr
var1 (InBndr -> Maybe Int -> SimplCont -> SimplCont
trimJoinCont InBndr
var (InBndr -> Maybe Int
isJoinId_maybe InBndr
var1) SimplCont
cont)
DoneEx e :: Expr InBndr
e mb_join :: Maybe Int
mb_join -> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF (SimplEnv -> SimplEnv
zapSubstEnv SimplEnv
env) Expr InBndr
e (InBndr -> Maybe Int -> SimplCont -> SimplCont
trimJoinCont InBndr
var Maybe Int
mb_join SimplCont
cont)
completeCall :: SimplEnv -> OutId -> SimplCont -> SimplM (SimplFloats, OutExpr)
completeCall :: SimplEnv
-> InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
completeCall env :: SimplEnv
env var :: InBndr
var cont :: SimplCont
cont
| Just expr :: Expr InBndr
expr <- DynFlags
-> InBndr
-> Bool
-> Bool
-> [ArgSummary]
-> CallCtxt
-> Maybe (Expr InBndr)
callSiteInline DynFlags
dflags InBndr
var Bool
active_unf
Bool
lone_variable [ArgSummary]
arg_infos CallCtxt
interesting_cont
= do { Tick -> SimplM ()
checkedTick (InBndr -> Tick
UnfoldingDone InBndr
var)
; Expr InBndr -> SimplCont -> SimplM ()
forall (m :: * -> *) a a.
(MonadIO m, Outputable a, Outputable a) =>
a -> a -> m ()
dump_inline Expr InBndr
expr SimplCont
cont
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF (SimplEnv -> SimplEnv
zapSubstEnv SimplEnv
env) Expr InBndr
expr SimplCont
cont }
| Bool
otherwise
= do { RuleEnv
rule_base <- SimplM RuleEnv
getSimplRules
; let info :: ArgInfo
info = SimplEnv -> InBndr -> [CoreRule] -> Int -> SimplCont -> ArgInfo
mkArgInfo SimplEnv
env InBndr
var (RuleEnv -> InBndr -> [CoreRule]
getRules RuleEnv
rule_base InBndr
var)
Int
n_val_args SimplCont
call_cont
; SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall SimplEnv
env ArgInfo
info SimplCont
cont }
where
dflags :: DynFlags
dflags = SimplEnv -> DynFlags
seDynFlags SimplEnv
env
(lone_variable :: Bool
lone_variable, arg_infos :: [ArgSummary]
arg_infos, call_cont :: SimplCont
call_cont) = SimplCont -> (Bool, [ArgSummary], SimplCont)
contArgs SimplCont
cont
n_val_args :: Int
n_val_args = [ArgSummary] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [ArgSummary]
arg_infos
interesting_cont :: CallCtxt
interesting_cont = SimplEnv -> SimplCont -> CallCtxt
interestingCallContext SimplEnv
env SimplCont
call_cont
active_unf :: Bool
active_unf = SimplMode -> InBndr -> Bool
activeUnfolding (SimplEnv -> SimplMode
getMode SimplEnv
env) InBndr
var
dump_inline :: a -> a -> m ()
dump_inline unfolding :: a
unfolding cont :: a
cont
| Bool -> Bool
not (DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_inlinings DynFlags
dflags) = () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
| Bool -> Bool
not (DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_verbose_core2core DynFlags
dflags)
= Bool -> m () -> m ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when (Name -> Bool
isExternalName (InBndr -> Name
idName InBndr
var)) (m () -> m ()) -> m () -> m ()
forall a b. (a -> b) -> a -> b
$
IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> PrintUnqualified -> SDoc -> IO ()
printOutputForUser DynFlags
dflags PrintUnqualified
alwaysQualify (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
sep [[Char] -> SDoc
text "Inlining done:", Int -> SDoc -> SDoc
nest 4 (InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
var)]
| Bool
otherwise
= IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> IO () -> m ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> PrintUnqualified -> SDoc -> IO ()
printOutputForUser DynFlags
dflags PrintUnqualified
alwaysQualify (SDoc -> IO ()) -> SDoc -> IO ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
sep [[Char] -> SDoc
text "Inlining done: " SDoc -> SDoc -> SDoc
<> InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
var,
Int -> SDoc -> SDoc
nest 4 ([SDoc] -> SDoc
vcat [[Char] -> SDoc
text "Inlined fn: " SDoc -> SDoc -> SDoc
<+> Int -> SDoc -> SDoc
nest 2 (a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
unfolding),
[Char] -> SDoc
text "Cont: " SDoc -> SDoc -> SDoc
<+> a -> SDoc
forall a. Outputable a => a -> SDoc
ppr a
cont])]
rebuildCall :: SimplEnv
-> ArgInfo
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
rebuildCall :: SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall env :: SimplEnv
env (ArgInfo { ai_fun :: ArgInfo -> InBndr
ai_fun = InBndr
fun, ai_args :: ArgInfo -> [ArgSpec]
ai_args = [ArgSpec]
rev_args, ai_strs :: ArgInfo -> [Bool]
ai_strs = [] }) cont :: SimplCont
cont
| Bool -> Bool
not (SimplCont -> Bool
contIsTrivial SimplCont
cont)
= OutType -> ()
seqType OutType
cont_ty ()
-> SimplM (SimplFloats, Expr InBndr)
-> SimplM (SimplFloats, Expr InBndr)
forall a b. a -> b -> b
`seq`
(SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, Expr InBndr -> OutType -> Expr InBndr
castBottomExpr Expr InBndr
res OutType
cont_ty)
where
res :: Expr InBndr
res = InBndr -> [ArgSpec] -> Expr InBndr
argInfoExpr InBndr
fun [ArgSpec]
rev_args
cont_ty :: OutType
cont_ty = SimplCont -> OutType
contResultType SimplCont
cont
rebuildCall env :: SimplEnv
env info :: ArgInfo
info@(ArgInfo { ai_fun :: ArgInfo -> InBndr
ai_fun = InBndr
fun, ai_args :: ArgInfo -> [ArgSpec]
ai_args = [ArgSpec]
rev_args
, ai_rules :: ArgInfo -> FunRules
ai_rules = Just (nr_wanted :: Int
nr_wanted, rules :: [CoreRule]
rules) }) cont :: SimplCont
cont
| Int
nr_wanted Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 0 Bool -> Bool -> Bool
|| Bool
no_more_args
, let info' :: ArgInfo
info' = ArgInfo
info { ai_rules :: FunRules
ai_rules = FunRules
forall a. Maybe a
Nothing }
=
do { Maybe (SimplEnv, Expr InBndr, SimplCont)
mb_match <- SimplEnv
-> [CoreRule]
-> InBndr
-> [ArgSpec]
-> SimplCont
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
tryRules SimplEnv
env [CoreRule]
rules InBndr
fun ([ArgSpec] -> [ArgSpec]
forall a. [a] -> [a]
reverse [ArgSpec]
rev_args) SimplCont
cont
; case Maybe (SimplEnv, Expr InBndr, SimplCont)
mb_match of
Just (env' :: SimplEnv
env', rhs :: Expr InBndr
rhs, cont' :: SimplCont
cont') -> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env' Expr InBndr
rhs SimplCont
cont'
Nothing -> SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall SimplEnv
env ArgInfo
info' SimplCont
cont }
where
no_more_args :: Bool
no_more_args = case SimplCont
cont of
ApplyToTy {} -> Bool
False
ApplyToVal {} -> Bool
False
_ -> Bool
True
rebuildCall env :: SimplEnv
env info :: ArgInfo
info (CastIt co :: Coercion
co cont :: SimplCont
cont)
= SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall SimplEnv
env (ArgInfo -> Coercion -> ArgInfo
addCastTo ArgInfo
info Coercion
co) SimplCont
cont
rebuildCall env :: SimplEnv
env info :: ArgInfo
info (ApplyToTy { sc_arg_ty :: SimplCont -> OutType
sc_arg_ty = OutType
arg_ty, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall SimplEnv
env (ArgInfo -> OutType -> ArgInfo
addTyArgTo ArgInfo
info OutType
arg_ty) SimplCont
cont
rebuildCall env :: SimplEnv
env info :: ArgInfo
info@(ArgInfo { ai_encl :: ArgInfo -> Bool
ai_encl = Bool
encl_rules, ai_type :: ArgInfo -> OutType
ai_type = OutType
fun_ty
, ai_strs :: ArgInfo -> [Bool]
ai_strs = str :: Bool
str:strs :: [Bool]
strs, ai_discs :: ArgInfo -> [Int]
ai_discs = disc :: Int
disc:discs :: [Int]
discs })
(ApplyToVal { sc_arg :: SimplCont -> Expr InBndr
sc_arg = Expr InBndr
arg, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
arg_se
, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup_flag, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
| DupFlag -> Bool
isSimplified DupFlag
dup_flag
= SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall SimplEnv
env (ArgInfo -> Expr InBndr -> ArgInfo
addValArgTo ArgInfo
info' Expr InBndr
arg) SimplCont
cont
| Bool
str
, SimplMode -> Bool
sm_case_case (SimplEnv -> SimplMode
getMode SimplEnv
env)
=
SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF (SimplEnv
arg_se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env) Expr InBndr
arg
(StrictArg :: DupFlag -> ArgInfo -> CallCtxt -> SimplCont -> SimplCont
StrictArg { sc_fun :: ArgInfo
sc_fun = ArgInfo
info', sc_cci :: CallCtxt
sc_cci = CallCtxt
cci_strict
, sc_dup :: DupFlag
sc_dup = DupFlag
Simplified, sc_cont :: SimplCont
sc_cont = SimplCont
cont })
| Bool
otherwise
= do { Expr InBndr
arg' <- SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC (SimplEnv
arg_se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env) Expr InBndr
arg
(OutType -> CallCtxt -> SimplCont
mkLazyArgStop OutType
arg_ty CallCtxt
cci_lazy)
; SimplEnv
-> ArgInfo -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuildCall SimplEnv
env (ArgInfo -> Expr InBndr -> ArgInfo
addValArgTo ArgInfo
info' Expr InBndr
arg') SimplCont
cont }
where
info' :: ArgInfo
info' = ArgInfo
info { ai_strs :: [Bool]
ai_strs = [Bool]
strs, ai_discs :: [Int]
ai_discs = [Int]
discs }
arg_ty :: OutType
arg_ty = OutType -> OutType
funArgTy OutType
fun_ty
cci_lazy :: CallCtxt
cci_lazy | Bool
encl_rules = CallCtxt
RuleArgCtxt
| Int
disc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0 = CallCtxt
DiscArgCtxt
| Bool
otherwise = CallCtxt
BoringCtxt
cci_strict :: CallCtxt
cci_strict | Bool
encl_rules = CallCtxt
RuleArgCtxt
| Int
disc Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> 0 = CallCtxt
DiscArgCtxt
| Bool
otherwise = CallCtxt
RhsCtxt
rebuildCall env :: SimplEnv
env (ArgInfo { ai_fun :: ArgInfo -> InBndr
ai_fun = InBndr
fun, ai_args :: ArgInfo -> [ArgSpec]
ai_args = [ArgSpec]
rev_args }) cont :: SimplCont
cont
= SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env (InBndr -> [ArgSpec] -> Expr InBndr
argInfoExpr InBndr
fun [ArgSpec]
rev_args) SimplCont
cont
tryRules :: SimplEnv -> [CoreRule]
-> Id -> [ArgSpec]
-> SimplCont
-> SimplM (Maybe (SimplEnv, CoreExpr, SimplCont))
tryRules :: SimplEnv
-> [CoreRule]
-> InBndr
-> [ArgSpec]
-> SimplCont
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
tryRules env :: SimplEnv
env rules :: [CoreRule]
rules fn :: InBndr
fn args :: [ArgSpec]
args call_cont :: SimplCont
call_cont
| [CoreRule] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreRule]
rules
= Maybe (SimplEnv, Expr InBndr, SimplCont)
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (SimplEnv, Expr InBndr, SimplCont)
forall a. Maybe a
Nothing
| Just (rule :: CoreRule
rule, rule_rhs :: Expr InBndr
rule_rhs) <- DynFlags
-> InScopeEnv
-> (Activation -> Bool)
-> InBndr
-> [Expr InBndr]
-> [CoreRule]
-> Maybe (CoreRule, Expr InBndr)
lookupRule DynFlags
dflags (SimplEnv -> InScopeEnv
getUnfoldingInRuleMatch SimplEnv
env)
(SimplMode -> Activation -> Bool
activeRule (SimplEnv -> SimplMode
getMode SimplEnv
env)) InBndr
fn
([ArgSpec] -> [Expr InBndr]
argInfoAppArgs [ArgSpec]
args) [CoreRule]
rules
= do { Tick -> SimplM ()
checkedTick (FastString -> Tick
RuleFired (CoreRule -> FastString
ruleName CoreRule
rule))
; let cont' :: SimplCont
cont' = SimplEnv -> [ArgSpec] -> SimplCont -> SimplCont
pushSimplifiedArgs SimplEnv
zapped_env
(Int -> [ArgSpec] -> [ArgSpec]
forall a. Int -> [a] -> [a]
drop (CoreRule -> Int
ruleArity CoreRule
rule) [ArgSpec]
args)
SimplCont
call_cont
occ_anald_rhs :: Expr InBndr
occ_anald_rhs = Expr InBndr -> Expr InBndr
occurAnalyseExpr Expr InBndr
rule_rhs
; CoreRule -> Expr InBndr -> SimplM ()
forall (m :: * -> *) b.
(MonadIO m, OutputableBndr b) =>
CoreRule -> Expr b -> m ()
dump CoreRule
rule Expr InBndr
rule_rhs
; Maybe (SimplEnv, Expr InBndr, SimplCont)
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
forall (m :: * -> *) a. Monad m => a -> m a
return ((SimplEnv, Expr InBndr, SimplCont)
-> Maybe (SimplEnv, Expr InBndr, SimplCont)
forall a. a -> Maybe a
Just (SimplEnv
zapped_env, Expr InBndr
occ_anald_rhs, SimplCont
cont')) }
| Bool
otherwise
= do { SimplM ()
nodump
; Maybe (SimplEnv, Expr InBndr, SimplCont)
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (SimplEnv, Expr InBndr, SimplCont)
forall a. Maybe a
Nothing }
where
dflags :: DynFlags
dflags = SimplEnv -> DynFlags
seDynFlags SimplEnv
env
zapped_env :: SimplEnv
zapped_env = SimplEnv -> SimplEnv
zapSubstEnv SimplEnv
env
printRuleModule :: CoreRule -> SDoc
printRuleModule rule :: CoreRule
rule
= SDoc -> SDoc
parens (SDoc -> (Module -> SDoc) -> Maybe Module -> SDoc
forall b a. b -> (a -> b) -> Maybe a -> b
maybe ([Char] -> SDoc
text "BUILTIN")
(ModuleName -> SDoc
pprModuleName (ModuleName -> SDoc) -> (Module -> ModuleName) -> Module -> SDoc
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Module -> ModuleName
moduleName)
(CoreRule -> Maybe Module
ruleModule CoreRule
rule))
dump :: CoreRule -> Expr b -> m ()
dump rule :: CoreRule
rule rule_rhs :: Expr b
rule_rhs
| DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_rule_rewrites DynFlags
dflags
= DynFlags -> DumpFlag -> [Char] -> SDoc -> m ()
forall (m :: * -> *).
MonadIO m =>
DynFlags -> DumpFlag -> [Char] -> SDoc -> m ()
log_rule DynFlags
dflags DumpFlag
Opt_D_dump_rule_rewrites "Rule fired" (SDoc -> m ()) -> SDoc -> m ()
forall a b. (a -> b) -> a -> b
$ [SDoc] -> SDoc
vcat
[ [Char] -> SDoc
text "Rule:" SDoc -> SDoc -> SDoc
<+> FastString -> SDoc
ftext (CoreRule -> FastString
ruleName CoreRule
rule)
, [Char] -> SDoc
text "Module:" SDoc -> SDoc -> SDoc
<+> CoreRule -> SDoc
printRuleModule CoreRule
rule
, [Char] -> SDoc
text "Before:" SDoc -> SDoc -> SDoc
<+> SDoc -> Int -> SDoc -> SDoc
hang (InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
fn) 2 ([SDoc] -> SDoc
sep ((ArgSpec -> SDoc) -> [ArgSpec] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map ArgSpec -> SDoc
forall a. Outputable a => a -> SDoc
ppr [ArgSpec]
args))
, [Char] -> SDoc
text "After: " SDoc -> SDoc -> SDoc
<+> Expr b -> SDoc
forall b. OutputableBndr b => Expr b -> SDoc
pprCoreExpr Expr b
rule_rhs
, [Char] -> SDoc
text "Cont: " SDoc -> SDoc -> SDoc
<+> SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
call_cont ]
| DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_rule_firings DynFlags
dflags
= DynFlags -> DumpFlag -> [Char] -> SDoc -> m ()
forall (m :: * -> *).
MonadIO m =>
DynFlags -> DumpFlag -> [Char] -> SDoc -> m ()
log_rule DynFlags
dflags DumpFlag
Opt_D_dump_rule_firings "Rule fired:" (SDoc -> m ()) -> SDoc -> m ()
forall a b. (a -> b) -> a -> b
$
FastString -> SDoc
ftext (CoreRule -> FastString
ruleName CoreRule
rule)
SDoc -> SDoc -> SDoc
<+> CoreRule -> SDoc
printRuleModule CoreRule
rule
| Bool
otherwise
= () -> m ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
nodump :: SimplM ()
nodump
| DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_rule_rewrites DynFlags
dflags
= IO () -> SimplM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> SimplM ()) -> IO () -> SimplM ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> PrintUnqualified -> DumpFlag -> [Char] -> SDoc -> IO ()
dumpSDoc DynFlags
dflags PrintUnqualified
alwaysQualify DumpFlag
Opt_D_dump_rule_rewrites "" SDoc
empty
| DumpFlag -> DynFlags -> Bool
dopt DumpFlag
Opt_D_dump_rule_firings DynFlags
dflags
= IO () -> SimplM ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> SimplM ()) -> IO () -> SimplM ()
forall a b. (a -> b) -> a -> b
$ DynFlags -> PrintUnqualified -> DumpFlag -> [Char] -> SDoc -> IO ()
dumpSDoc DynFlags
dflags PrintUnqualified
alwaysQualify DumpFlag
Opt_D_dump_rule_firings "" SDoc
empty
| Bool
otherwise
= () -> SimplM ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()
log_rule :: DynFlags -> DumpFlag -> [Char] -> SDoc -> m ()
log_rule dflags :: DynFlags
dflags flag :: DumpFlag
flag hdr :: [Char]
hdr details :: SDoc
details
= IO () -> m ()
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> m ()) -> (SDoc -> IO ()) -> SDoc -> m ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DynFlags -> PrintUnqualified -> DumpFlag -> [Char] -> SDoc -> IO ()
dumpSDoc DynFlags
dflags PrintUnqualified
alwaysQualify DumpFlag
flag "" (SDoc -> m ()) -> SDoc -> m ()
forall a b. (a -> b) -> a -> b
$
[SDoc] -> SDoc
sep [[Char] -> SDoc
text [Char]
hdr, Int -> SDoc -> SDoc
nest 4 SDoc
details]
trySeqRules :: SimplEnv
-> OutExpr -> InExpr
-> SimplCont
-> SimplM (Maybe (SimplEnv, CoreExpr, SimplCont))
trySeqRules :: SimplEnv
-> Expr InBndr
-> Expr InBndr
-> SimplCont
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
trySeqRules in_env :: SimplEnv
in_env scrut :: Expr InBndr
scrut rhs :: Expr InBndr
rhs cont :: SimplCont
cont
= do { RuleEnv
rule_base <- SimplM RuleEnv
getSimplRules
; SimplEnv
-> [CoreRule]
-> InBndr
-> [ArgSpec]
-> SimplCont
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
tryRules SimplEnv
in_env (RuleEnv -> InBndr -> [CoreRule]
getRules RuleEnv
rule_base InBndr
seqId) InBndr
seqId [ArgSpec]
out_args SimplCont
rule_cont }
where
no_cast_scrut :: Expr InBndr
no_cast_scrut = Expr InBndr -> Expr InBndr
forall b. Expr b -> Expr b
drop_casts Expr InBndr
scrut
scrut_ty :: OutType
scrut_ty = Expr InBndr -> OutType
exprType Expr InBndr
no_cast_scrut
seq_id_ty :: OutType
seq_id_ty = InBndr -> OutType
idType InBndr
seqId
rhs_ty :: OutType
rhs_ty = SimplEnv -> OutType -> OutType
substTy SimplEnv
in_env (Expr InBndr -> OutType
exprType Expr InBndr
rhs)
out_args :: [ArgSpec]
out_args = [ TyArg :: OutType -> OutType -> ArgSpec
TyArg { as_arg_ty :: OutType
as_arg_ty = OutType
scrut_ty
, as_hole_ty :: OutType
as_hole_ty = OutType
seq_id_ty }
, TyArg :: OutType -> OutType -> ArgSpec
TyArg { as_arg_ty :: OutType
as_arg_ty = OutType
rhs_ty
, as_hole_ty :: OutType
as_hole_ty = HasDebugCallStack => OutType -> OutType -> OutType
OutType -> OutType -> OutType
piResultTy OutType
seq_id_ty OutType
scrut_ty }
, Expr InBndr -> ArgSpec
ValArg Expr InBndr
no_cast_scrut]
rule_cont :: SimplCont
rule_cont = ApplyToVal :: DupFlag -> Expr InBndr -> SimplEnv -> SimplCont -> SimplCont
ApplyToVal { sc_dup :: DupFlag
sc_dup = DupFlag
NoDup, sc_arg :: Expr InBndr
sc_arg = Expr InBndr
rhs
, sc_env :: SimplEnv
sc_env = SimplEnv
in_env, sc_cont :: SimplCont
sc_cont = SimplCont
cont }
drop_casts :: Expr b -> Expr b
drop_casts (Cast e :: Expr b
e _) = Expr b -> Expr b
drop_casts Expr b
e
drop_casts e :: Expr b
e = Expr b
e
rebuildCase, reallyRebuildCase
:: SimplEnv
-> OutExpr
-> InId
-> [InAlt]
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
rebuildCase :: SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
rebuildCase env :: SimplEnv
env scrut :: Expr InBndr
scrut case_bndr :: InBndr
case_bndr alts :: [Alt InBndr]
alts cont :: SimplCont
cont
| Lit lit :: Literal
lit <- Expr InBndr
scrut
, Bool -> Bool
not (Literal -> Bool
litIsLifted Literal
lit)
= do { Tick -> SimplM ()
tick (InBndr -> Tick
KnownBranch InBndr
case_bndr)
; case AltCon -> [Alt InBndr] -> Maybe (Alt InBndr)
forall a b. AltCon -> [(AltCon, a, b)] -> Maybe (AltCon, a, b)
findAlt (Literal -> AltCon
LitAlt Literal
lit) [Alt InBndr]
alts of
Nothing -> SimplEnv
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
missingAlt SimplEnv
env InBndr
case_bndr [Alt InBndr]
alts SimplCont
cont
Just (_, bs :: [InBndr]
bs, rhs :: Expr InBndr
rhs) -> [InBndr] -> Expr InBndr -> SimplM (SimplFloats, Expr InBndr)
forall (t :: * -> *) a.
Foldable t =>
t a -> Expr InBndr -> SimplM (SimplFloats, Expr InBndr)
simple_rhs [InBndr]
bs Expr InBndr
rhs }
| Just (con :: DataCon
con, ty_args :: [OutType]
ty_args, other_args :: [Expr InBndr]
other_args) <- InScopeEnv
-> Expr InBndr -> Maybe (DataCon, [OutType], [Expr InBndr])
exprIsConApp_maybe (SimplEnv -> InScopeEnv
getUnfoldingInRuleMatch SimplEnv
env) Expr InBndr
scrut
= do { Tick -> SimplM ()
tick (InBndr -> Tick
KnownBranch InBndr
case_bndr)
; case AltCon -> [Alt InBndr] -> Maybe (Alt InBndr)
forall a b. AltCon -> [(AltCon, a, b)] -> Maybe (AltCon, a, b)
findAlt (DataCon -> AltCon
DataAlt DataCon
con) [Alt InBndr]
alts of
Nothing -> SimplEnv
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
missingAlt SimplEnv
env InBndr
case_bndr [Alt InBndr]
alts SimplCont
cont
Just (DEFAULT, bs :: [InBndr]
bs, rhs :: Expr InBndr
rhs) -> [InBndr] -> Expr InBndr -> SimplM (SimplFloats, Expr InBndr)
forall (t :: * -> *) a.
Foldable t =>
t a -> Expr InBndr -> SimplM (SimplFloats, Expr InBndr)
simple_rhs [InBndr]
bs Expr InBndr
rhs
Just (_, bs :: [InBndr]
bs, rhs :: Expr InBndr
rhs) -> SimplEnv
-> Expr InBndr
-> DataCon
-> [OutType]
-> [Expr InBndr]
-> InBndr
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
knownCon SimplEnv
env Expr InBndr
scrut DataCon
con [OutType]
ty_args [Expr InBndr]
other_args
InBndr
case_bndr [InBndr]
bs Expr InBndr
rhs SimplCont
cont
}
where
simple_rhs :: t a -> Expr InBndr -> SimplM (SimplFloats, Expr InBndr)
simple_rhs bs :: t a
bs rhs :: Expr InBndr
rhs = ASSERT( null bs )
do { (floats1 :: SimplFloats
floats1, env' :: SimplEnv
env') <- SimplEnv -> InBndr -> Expr InBndr -> SimplM (SimplFloats, SimplEnv)
simplNonRecX SimplEnv
env InBndr
case_bndr Expr InBndr
scrut
; (floats2 :: SimplFloats
floats2, expr' :: Expr InBndr
expr') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env' Expr InBndr
rhs SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
expr') }
rebuildCase env :: SimplEnv
env scrut :: Expr InBndr
scrut case_bndr :: InBndr
case_bndr alts :: [Alt InBndr]
alts@[(_, bndrs :: [InBndr]
bndrs, rhs :: Expr InBndr
rhs)] cont :: SimplCont
cont
| Bool
is_plain_seq
, Expr InBndr -> Bool
exprOkForSideEffects Expr InBndr
scrut
= SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env Expr InBndr
rhs SimplCont
cont
| Bool
all_dead_bndrs
, Expr InBndr -> InBndr -> Bool
doCaseToLet Expr InBndr
scrut InBndr
case_bndr
= do { Tick -> SimplM ()
tick (InBndr -> Tick
CaseElim InBndr
case_bndr)
; (floats1 :: SimplFloats
floats1, env' :: SimplEnv
env') <- SimplEnv -> InBndr -> Expr InBndr -> SimplM (SimplFloats, SimplEnv)
simplNonRecX SimplEnv
env InBndr
case_bndr Expr InBndr
scrut
; (floats2 :: SimplFloats
floats2, expr' :: Expr InBndr
expr') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env' Expr InBndr
rhs SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, Expr InBndr
expr') }
| Bool
is_plain_seq
= do { Maybe (SimplEnv, Expr InBndr, SimplCont)
mb_rule <- SimplEnv
-> Expr InBndr
-> Expr InBndr
-> SimplCont
-> SimplM (Maybe (SimplEnv, Expr InBndr, SimplCont))
trySeqRules SimplEnv
env Expr InBndr
scrut Expr InBndr
rhs SimplCont
cont
; case Maybe (SimplEnv, Expr InBndr, SimplCont)
mb_rule of
Just (env' :: SimplEnv
env', rule_rhs :: Expr InBndr
rule_rhs, cont' :: SimplCont
cont') -> SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env' Expr InBndr
rule_rhs SimplCont
cont'
Nothing -> SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
reallyRebuildCase SimplEnv
env Expr InBndr
scrut InBndr
case_bndr [Alt InBndr]
alts SimplCont
cont }
where
all_dead_bndrs :: Bool
all_dead_bndrs = (InBndr -> Bool) -> [InBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all InBndr -> Bool
isDeadBinder [InBndr]
bndrs
is_plain_seq :: Bool
is_plain_seq = Bool
all_dead_bndrs Bool -> Bool -> Bool
&& InBndr -> Bool
isDeadBinder InBndr
case_bndr
rebuildCase env :: SimplEnv
env scrut :: Expr InBndr
scrut case_bndr :: InBndr
case_bndr alts :: [Alt InBndr]
alts cont :: SimplCont
cont
= SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
reallyRebuildCase SimplEnv
env Expr InBndr
scrut InBndr
case_bndr [Alt InBndr]
alts SimplCont
cont
doCaseToLet :: OutExpr
-> InId
-> Bool
doCaseToLet :: Expr InBndr -> InBndr -> Bool
doCaseToLet scrut :: Expr InBndr
scrut case_bndr :: InBndr
case_bndr
| InBndr -> Bool
isTyCoVar InBndr
case_bndr
= Expr InBndr -> Bool
forall b. Expr b -> Bool
isTyCoArg Expr InBndr
scrut
| HasDebugCallStack => OutType -> Bool
OutType -> Bool
isUnliftedType (InBndr -> OutType
idType InBndr
case_bndr)
= Expr InBndr -> Bool
exprOkForSpeculation Expr InBndr
scrut
| Bool
otherwise
= Expr InBndr -> Bool
exprIsHNF Expr InBndr
scrut
Bool -> Bool -> Bool
|| Demand -> Bool
forall s u. JointDmd (Str s) (Use u) -> Bool
isStrictDmd (InBndr -> Demand
idDemandInfo InBndr
case_bndr)
reallyRebuildCase :: SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
reallyRebuildCase env :: SimplEnv
env scrut :: Expr InBndr
scrut case_bndr :: InBndr
case_bndr alts :: [Alt InBndr]
alts cont :: SimplCont
cont
| Bool -> Bool
not (SimplMode -> Bool
sm_case_case (SimplEnv -> SimplMode
getMode SimplEnv
env))
= do { Expr InBndr
case_expr <- SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (Expr InBndr)
simplAlts SimplEnv
env Expr InBndr
scrut InBndr
case_bndr [Alt InBndr]
alts
(OutType -> SimplCont
mkBoringStop (SimplCont -> OutType
contHoleType SimplCont
cont))
; SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
rebuild SimplEnv
env Expr InBndr
case_expr SimplCont
cont }
| Bool
otherwise
= do { (floats :: SimplFloats
floats, cont' :: SimplCont
cont') <- SimplEnv
-> [Alt InBndr] -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCaseCont SimplEnv
env [Alt InBndr]
alts SimplCont
cont
; Expr InBndr
case_expr <- SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (Expr InBndr)
simplAlts (SimplEnv
env SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
floats)
Expr InBndr
scrut InBndr
case_bndr [Alt InBndr]
alts SimplCont
cont'
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, Expr InBndr
case_expr) }
simplAlts :: SimplEnv
-> OutExpr
-> InId
-> [InAlt]
-> SimplCont
-> SimplM OutExpr
simplAlts :: SimplEnv
-> Expr InBndr
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (Expr InBndr)
simplAlts env0 :: SimplEnv
env0 scrut :: Expr InBndr
scrut case_bndr :: InBndr
case_bndr alts :: [Alt InBndr]
alts cont' :: SimplCont
cont'
= do { [Char] -> SDoc -> SimplM ()
traceSmpl "simplAlts" ([SDoc] -> SDoc
vcat [ InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
case_bndr
, [Char] -> SDoc
text "cont':" SDoc -> SDoc -> SDoc
<+> SimplCont -> SDoc
forall a. Outputable a => a -> SDoc
ppr SimplCont
cont'
, [Char] -> SDoc
text "in_scope" SDoc -> SDoc -> SDoc
<+> InScopeSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr (SimplEnv -> InScopeSet
seInScope SimplEnv
env0) ])
; (env1 :: SimplEnv
env1, case_bndr1 :: InBndr
case_bndr1) <- SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplBinder SimplEnv
env0 InBndr
case_bndr
; let case_bndr2 :: InBndr
case_bndr2 = InBndr
case_bndr1 InBndr -> Unfolding -> InBndr
`setIdUnfolding` Unfolding
evaldUnfolding
env2 :: SimplEnv
env2 = SimplEnv -> InBndr -> SimplEnv
modifyInScope SimplEnv
env1 InBndr
case_bndr2
; (FamInstEnv, FamInstEnv)
fam_envs <- SimplM (FamInstEnv, FamInstEnv)
getFamEnvs
; (alt_env' :: SimplEnv
alt_env', scrut' :: Expr InBndr
scrut', case_bndr' :: InBndr
case_bndr') <- (FamInstEnv, FamInstEnv)
-> SimplEnv
-> Expr InBndr
-> InBndr
-> InBndr
-> [Alt InBndr]
-> SimplM (SimplEnv, Expr InBndr, InBndr)
improveSeq (FamInstEnv, FamInstEnv)
fam_envs SimplEnv
env2 Expr InBndr
scrut
InBndr
case_bndr InBndr
case_bndr2 [Alt InBndr]
alts
; (imposs_deflt_cons :: [AltCon]
imposs_deflt_cons, in_alts :: [Alt InBndr]
in_alts) <- Expr InBndr
-> InBndr -> [Alt InBndr] -> SimplM ([AltCon], [Alt InBndr])
prepareAlts Expr InBndr
scrut' InBndr
case_bndr' [Alt InBndr]
alts
; [Alt InBndr]
alts' <- (Alt InBndr -> SimplM (Alt InBndr))
-> [Alt InBndr] -> SimplM [Alt InBndr]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (SimplEnv
-> Maybe (Expr InBndr)
-> [AltCon]
-> InBndr
-> SimplCont
-> Alt InBndr
-> SimplM (Alt InBndr)
simplAlt SimplEnv
alt_env' (Expr InBndr -> Maybe (Expr InBndr)
forall a. a -> Maybe a
Just Expr InBndr
scrut') [AltCon]
imposs_deflt_cons InBndr
case_bndr' SimplCont
cont') [Alt InBndr]
in_alts
;
; let alts_ty' :: OutType
alts_ty' = SimplCont -> OutType
contResultType SimplCont
cont'
; OutType -> ()
seqType OutType
alts_ty' () -> SimplM (Expr InBndr) -> SimplM (Expr InBndr)
forall a b. a -> b -> b
`seq`
DynFlags
-> Expr InBndr
-> InBndr
-> OutType
-> [Alt InBndr]
-> SimplM (Expr InBndr)
mkCase (SimplEnv -> DynFlags
seDynFlags SimplEnv
env0) Expr InBndr
scrut' InBndr
case_bndr' OutType
alts_ty' [Alt InBndr]
alts' }
improveSeq :: (FamInstEnv, FamInstEnv) -> SimplEnv
-> OutExpr -> InId -> OutId -> [InAlt]
-> SimplM (SimplEnv, OutExpr, OutId)
improveSeq :: (FamInstEnv, FamInstEnv)
-> SimplEnv
-> Expr InBndr
-> InBndr
-> InBndr
-> [Alt InBndr]
-> SimplM (SimplEnv, Expr InBndr, InBndr)
improveSeq fam_envs :: (FamInstEnv, FamInstEnv)
fam_envs env :: SimplEnv
env scrut :: Expr InBndr
scrut case_bndr :: InBndr
case_bndr case_bndr1 :: InBndr
case_bndr1 [(DEFAULT,_,_)]
| Just (co :: Coercion
co, ty2 :: OutType
ty2) <- (FamInstEnv, FamInstEnv) -> OutType -> Maybe (Coercion, OutType)
topNormaliseType_maybe (FamInstEnv, FamInstEnv)
fam_envs (InBndr -> OutType
idType InBndr
case_bndr1)
= do { InBndr
case_bndr2 <- FastString -> OutType -> SimplM InBndr
newId ([Char] -> FastString
fsLit "nt") OutType
ty2
; let rhs :: SimplSR
rhs = Expr InBndr -> Maybe Int -> SimplSR
DoneEx (InBndr -> Expr InBndr
forall b. InBndr -> Expr b
Var InBndr
case_bndr2 Expr InBndr -> Coercion -> Expr InBndr
forall b. Expr b -> Coercion -> Expr b
`Cast` Coercion -> Coercion
mkSymCo Coercion
co) Maybe Int
forall a. Maybe a
Nothing
env2 :: SimplEnv
env2 = SimplEnv -> InBndr -> SimplSR -> SimplEnv
extendIdSubst SimplEnv
env InBndr
case_bndr SimplSR
rhs
; (SimplEnv, Expr InBndr, InBndr)
-> SimplM (SimplEnv, Expr InBndr, InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env2, Expr InBndr
scrut Expr InBndr -> Coercion -> Expr InBndr
forall b. Expr b -> Coercion -> Expr b
`Cast` Coercion
co, InBndr
case_bndr2) }
improveSeq _ env :: SimplEnv
env scrut :: Expr InBndr
scrut _ case_bndr1 :: InBndr
case_bndr1 _
= (SimplEnv, Expr InBndr, InBndr)
-> SimplM (SimplEnv, Expr InBndr, InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env, Expr InBndr
scrut, InBndr
case_bndr1)
simplAlt :: SimplEnv
-> Maybe OutExpr
-> [AltCon]
-> OutId
-> SimplCont
-> InAlt
-> SimplM OutAlt
simplAlt :: SimplEnv
-> Maybe (Expr InBndr)
-> [AltCon]
-> InBndr
-> SimplCont
-> Alt InBndr
-> SimplM (Alt InBndr)
simplAlt env :: SimplEnv
env _ imposs_deflt_cons :: [AltCon]
imposs_deflt_cons case_bndr' :: InBndr
case_bndr' cont' :: SimplCont
cont' (DEFAULT, bndrs :: [InBndr]
bndrs, rhs :: Expr InBndr
rhs)
= ASSERT( null bndrs )
do { let env' :: SimplEnv
env' = SimplEnv -> InBndr -> Unfolding -> SimplEnv
addBinderUnfolding SimplEnv
env InBndr
case_bndr'
([AltCon] -> Unfolding
mkOtherCon [AltCon]
imposs_deflt_cons)
; Expr InBndr
rhs' <- SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC SimplEnv
env' Expr InBndr
rhs SimplCont
cont'
; Alt InBndr -> SimplM (Alt InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (AltCon
DEFAULT, [], Expr InBndr
rhs') }
simplAlt env :: SimplEnv
env scrut' :: Maybe (Expr InBndr)
scrut' _ case_bndr' :: InBndr
case_bndr' cont' :: SimplCont
cont' (LitAlt lit :: Literal
lit, bndrs :: [InBndr]
bndrs, rhs :: Expr InBndr
rhs)
= ASSERT( null bndrs )
do { SimplEnv
env' <- SimplEnv
-> Maybe (Expr InBndr) -> InBndr -> Expr InBndr -> SimplM SimplEnv
addAltUnfoldings SimplEnv
env Maybe (Expr InBndr)
scrut' InBndr
case_bndr' (Literal -> Expr InBndr
forall b. Literal -> Expr b
Lit Literal
lit)
; Expr InBndr
rhs' <- SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC SimplEnv
env' Expr InBndr
rhs SimplCont
cont'
; Alt InBndr -> SimplM (Alt InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (Literal -> AltCon
LitAlt Literal
lit, [], Expr InBndr
rhs') }
simplAlt env :: SimplEnv
env scrut' :: Maybe (Expr InBndr)
scrut' _ case_bndr' :: InBndr
case_bndr' cont' :: SimplCont
cont' (DataAlt con :: DataCon
con, vs :: [InBndr]
vs, rhs :: Expr InBndr
rhs)
= do {
let vs_with_evals :: [InBndr]
vs_with_evals = Maybe (Expr InBndr) -> DataCon -> [InBndr] -> [InBndr]
addEvals Maybe (Expr InBndr)
scrut' DataCon
con [InBndr]
vs
; (env' :: SimplEnv
env', vs' :: [InBndr]
vs') <- SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
simplLamBndrs SimplEnv
env [InBndr]
vs_with_evals
; let inst_tys' :: [OutType]
inst_tys' = OutType -> [OutType]
tyConAppArgs (InBndr -> OutType
idType InBndr
case_bndr')
con_app :: OutExpr
con_app :: Expr InBndr
con_app = DataCon -> [OutType] -> [InBndr] -> Expr InBndr
forall b. DataCon -> [OutType] -> [InBndr] -> Expr b
mkConApp2 DataCon
con [OutType]
inst_tys' [InBndr]
vs'
; SimplEnv
env'' <- SimplEnv
-> Maybe (Expr InBndr) -> InBndr -> Expr InBndr -> SimplM SimplEnv
addAltUnfoldings SimplEnv
env' Maybe (Expr InBndr)
scrut' InBndr
case_bndr' Expr InBndr
con_app
; Expr InBndr
rhs' <- SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC SimplEnv
env'' Expr InBndr
rhs SimplCont
cont'
; Alt InBndr -> SimplM (Alt InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (DataCon -> AltCon
DataAlt DataCon
con, [InBndr]
vs', Expr InBndr
rhs') }
addEvals :: Maybe OutExpr -> DataCon -> [Id] -> [Id]
addEvals :: Maybe (Expr InBndr) -> DataCon -> [InBndr] -> [InBndr]
addEvals scrut :: Maybe (Expr InBndr)
scrut con :: DataCon
con vs :: [InBndr]
vs
| Just scr :: Expr InBndr
scr <- Maybe (Expr InBndr)
scrut
, DataCon -> Bool
isUnboxedTupleCon DataCon
con
, [s :: InBndr
s,x :: InBndr
x] <- [InBndr]
vs
, Just (Var f :: InBndr
f) <- Word -> Expr InBndr -> Maybe (Expr InBndr)
forall a. Word -> Expr a -> Maybe (Expr a)
stripNArgs 4 Expr InBndr
scr
, Just SeqOp <- InBndr -> Maybe PrimOp
isPrimOpId_maybe InBndr
f
, let x' :: InBndr
x' = StrictnessMark -> InBndr -> InBndr
zapIdOccInfoAndSetEvald StrictnessMark
MarkedStrict InBndr
x
= [InBndr
s, InBndr
x']
addEvals _scrut :: Maybe (Expr InBndr)
_scrut con :: DataCon
con vs :: [InBndr]
vs = [InBndr] -> [StrictnessMark] -> [InBndr]
go [InBndr]
vs [StrictnessMark]
the_strs
where
the_strs :: [StrictnessMark]
the_strs = DataCon -> [StrictnessMark]
dataConRepStrictness DataCon
con
go :: [InBndr] -> [StrictnessMark] -> [InBndr]
go [] [] = []
go (v :: InBndr
v:vs' :: [InBndr]
vs') strs :: [StrictnessMark]
strs | InBndr -> Bool
isTyVar InBndr
v = InBndr
v InBndr -> [InBndr] -> [InBndr]
forall a. a -> [a] -> [a]
: [InBndr] -> [StrictnessMark] -> [InBndr]
go [InBndr]
vs' [StrictnessMark]
strs
go (v :: InBndr
v:vs' :: [InBndr]
vs') (str :: StrictnessMark
str:strs :: [StrictnessMark]
strs) = StrictnessMark -> InBndr -> InBndr
zapIdOccInfoAndSetEvald StrictnessMark
str InBndr
v InBndr -> [InBndr] -> [InBndr]
forall a. a -> [a] -> [a]
: [InBndr] -> [StrictnessMark] -> [InBndr]
go [InBndr]
vs' [StrictnessMark]
strs
go _ _ = [Char] -> SDoc -> [InBndr]
forall a. HasCallStack => [Char] -> SDoc -> a
pprPanic "Simplify.addEvals"
(DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
con SDoc -> SDoc -> SDoc
$$
[InBndr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [InBndr]
vs SDoc -> SDoc -> SDoc
$$
[[Char]] -> SDoc
forall (t :: * -> *) a.
(Outputable (t a), Foldable t) =>
t a -> SDoc
ppr_with_length ((StrictnessMark -> [Char]) -> [StrictnessMark] -> [[Char]]
forall a b. (a -> b) -> [a] -> [b]
map StrictnessMark -> [Char]
strdisp [StrictnessMark]
the_strs) SDoc -> SDoc -> SDoc
$$
[OutType] -> SDoc
forall (t :: * -> *) a.
(Outputable (t a), Foldable t) =>
t a -> SDoc
ppr_with_length (DataCon -> [OutType]
dataConRepArgTys DataCon
con) SDoc -> SDoc -> SDoc
$$
[StrictnessMark] -> SDoc
forall (t :: * -> *) a.
(Outputable (t a), Foldable t) =>
t a -> SDoc
ppr_with_length (DataCon -> [StrictnessMark]
dataConRepStrictness DataCon
con))
where
ppr_with_length :: t a -> SDoc
ppr_with_length list :: t a
list
= t a -> SDoc
forall a. Outputable a => a -> SDoc
ppr t a
list SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
parens ([Char] -> SDoc
text "length =" SDoc -> SDoc -> SDoc
<+> Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr (t a -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length t a
list))
strdisp :: StrictnessMark -> [Char]
strdisp MarkedStrict = "MarkedStrict"
strdisp NotMarkedStrict = "NotMarkedStrict"
zapIdOccInfoAndSetEvald :: StrictnessMark -> Id -> Id
zapIdOccInfoAndSetEvald :: StrictnessMark -> InBndr -> InBndr
zapIdOccInfoAndSetEvald str :: StrictnessMark
str v :: InBndr
v =
StrictnessMark -> InBndr -> InBndr
setCaseBndrEvald StrictnessMark
str (InBndr -> InBndr) -> InBndr -> InBndr
forall a b. (a -> b) -> a -> b
$
InBndr -> InBndr
zapIdOccInfo InBndr
v
addAltUnfoldings :: SimplEnv -> Maybe OutExpr -> OutId -> OutExpr -> SimplM SimplEnv
addAltUnfoldings :: SimplEnv
-> Maybe (Expr InBndr) -> InBndr -> Expr InBndr -> SimplM SimplEnv
addAltUnfoldings env :: SimplEnv
env scrut :: Maybe (Expr InBndr)
scrut case_bndr :: InBndr
case_bndr con_app :: Expr InBndr
con_app
= do { let con_app_unf :: Unfolding
con_app_unf = Expr InBndr -> Unfolding
mk_simple_unf Expr InBndr
con_app
env1 :: SimplEnv
env1 = SimplEnv -> InBndr -> Unfolding -> SimplEnv
addBinderUnfolding SimplEnv
env InBndr
case_bndr Unfolding
con_app_unf
env2 :: SimplEnv
env2 = case Maybe (Expr InBndr)
scrut of
Just (Var v :: InBndr
v) -> SimplEnv -> InBndr -> Unfolding -> SimplEnv
addBinderUnfolding SimplEnv
env1 InBndr
v Unfolding
con_app_unf
Just (Cast (Var v :: InBndr
v) co :: Coercion
co) -> SimplEnv -> InBndr -> Unfolding -> SimplEnv
addBinderUnfolding SimplEnv
env1 InBndr
v (Unfolding -> SimplEnv) -> Unfolding -> SimplEnv
forall a b. (a -> b) -> a -> b
$
Expr InBndr -> Unfolding
mk_simple_unf (Expr InBndr -> Coercion -> Expr InBndr
forall b. Expr b -> Coercion -> Expr b
Cast Expr InBndr
con_app (Coercion -> Coercion
mkSymCo Coercion
co))
_ -> SimplEnv
env1
; [Char] -> SDoc -> SimplM ()
traceSmpl "addAltUnf" ([SDoc] -> SDoc
vcat [InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr InBndr
case_bndr SDoc -> SDoc -> SDoc
<+> Maybe (Expr InBndr) -> SDoc
forall a. Outputable a => a -> SDoc
ppr Maybe (Expr InBndr)
scrut, Expr InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr Expr InBndr
con_app])
; SimplEnv -> SimplM SimplEnv
forall (m :: * -> *) a. Monad m => a -> m a
return SimplEnv
env2 }
where
mk_simple_unf :: Expr InBndr -> Unfolding
mk_simple_unf = DynFlags -> Expr InBndr -> Unfolding
mkSimpleUnfolding (SimplEnv -> DynFlags
seDynFlags SimplEnv
env)
addBinderUnfolding :: SimplEnv -> Id -> Unfolding -> SimplEnv
addBinderUnfolding :: SimplEnv -> InBndr -> Unfolding -> SimplEnv
addBinderUnfolding env :: SimplEnv
env bndr :: InBndr
bndr unf :: Unfolding
unf
| Bool
debugIsOn, Just tmpl :: Expr InBndr
tmpl <- Unfolding -> Maybe (Expr InBndr)
maybeUnfoldingTemplate Unfolding
unf
= WARN( not (eqType (idType bndr) (exprType tmpl)),
ppr bndr $$ ppr (idType bndr) $$ ppr tmpl $$ ppr (exprType tmpl) )
SimplEnv -> InBndr -> SimplEnv
modifyInScope SimplEnv
env (InBndr
bndr InBndr -> Unfolding -> InBndr
`setIdUnfolding` Unfolding
unf)
| Bool
otherwise
= SimplEnv -> InBndr -> SimplEnv
modifyInScope SimplEnv
env (InBndr
bndr InBndr -> Unfolding -> InBndr
`setIdUnfolding` Unfolding
unf)
zapBndrOccInfo :: Bool -> Id -> Id
zapBndrOccInfo :: Bool -> InBndr -> InBndr
zapBndrOccInfo keep_occ_info :: Bool
keep_occ_info pat_id :: InBndr
pat_id
| Bool
keep_occ_info = InBndr
pat_id
| Bool
otherwise = InBndr -> InBndr
zapIdOccInfo InBndr
pat_id
knownCon :: SimplEnv
-> OutExpr
-> DataCon -> [OutType] -> [OutExpr]
-> InId -> [InBndr] -> InExpr
-> SimplCont
-> SimplM (SimplFloats, OutExpr)
knownCon :: SimplEnv
-> Expr InBndr
-> DataCon
-> [OutType]
-> [Expr InBndr]
-> InBndr
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
knownCon env :: SimplEnv
env scrut :: Expr InBndr
scrut dc :: DataCon
dc dc_ty_args :: [OutType]
dc_ty_args dc_args :: [Expr InBndr]
dc_args bndr :: InBndr
bndr bs :: [InBndr]
bs rhs :: Expr InBndr
rhs cont :: SimplCont
cont
= do { (floats1 :: SimplFloats
floats1, env1 :: SimplEnv
env1) <- SimplEnv
-> [InBndr] -> [Expr InBndr] -> SimplM (SimplFloats, SimplEnv)
bind_args SimplEnv
env [InBndr]
bs [Expr InBndr]
dc_args
; (floats2 :: SimplFloats
floats2, env2 :: SimplEnv
env2) <- SimplEnv -> SimplM (SimplFloats, SimplEnv)
bind_case_bndr SimplEnv
env1
; (floats3 :: SimplFloats
floats3, expr' :: Expr InBndr
expr') <- SimplEnv
-> Expr InBndr -> SimplCont -> SimplM (SimplFloats, Expr InBndr)
simplExprF SimplEnv
env2 Expr InBndr
rhs SimplCont
cont
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats3, Expr InBndr
expr') }
where
zap_occ :: InBndr -> InBndr
zap_occ = Bool -> InBndr -> InBndr
zapBndrOccInfo (InBndr -> Bool
isDeadBinder InBndr
bndr)
bind_args :: SimplEnv
-> [InBndr] -> [Expr InBndr] -> SimplM (SimplFloats, SimplEnv)
bind_args env' :: SimplEnv
env' [] _ = (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env', SimplEnv
env')
bind_args env' :: SimplEnv
env' (b :: InBndr
b:bs' :: [InBndr]
bs') (Type ty :: OutType
ty : args :: [Expr InBndr]
args)
= ASSERT( isTyVar b )
SimplEnv
-> [InBndr] -> [Expr InBndr] -> SimplM (SimplFloats, SimplEnv)
bind_args (SimplEnv -> InBndr -> OutType -> SimplEnv
extendTvSubst SimplEnv
env' InBndr
b OutType
ty) [InBndr]
bs' [Expr InBndr]
args
bind_args env' :: SimplEnv
env' (b :: InBndr
b:bs' :: [InBndr]
bs') (Coercion co :: Coercion
co : args :: [Expr InBndr]
args)
= ASSERT( isCoVar b )
SimplEnv
-> [InBndr] -> [Expr InBndr] -> SimplM (SimplFloats, SimplEnv)
bind_args (SimplEnv -> InBndr -> Coercion -> SimplEnv
extendCvSubst SimplEnv
env' InBndr
b Coercion
co) [InBndr]
bs' [Expr InBndr]
args
bind_args env' :: SimplEnv
env' (b :: InBndr
b:bs' :: [InBndr]
bs') (arg :: Expr InBndr
arg : args :: [Expr InBndr]
args)
= ASSERT( isId b )
do { let b' :: InBndr
b' = InBndr -> InBndr
zap_occ InBndr
b
; (floats1 :: SimplFloats
floats1, env2 :: SimplEnv
env2) <- SimplEnv -> InBndr -> Expr InBndr -> SimplM (SimplFloats, SimplEnv)
simplNonRecX SimplEnv
env' InBndr
b' Expr InBndr
arg
; (floats2 :: SimplFloats
floats2, env3 :: SimplEnv
env3) <- SimplEnv
-> [InBndr] -> [Expr InBndr] -> SimplM (SimplFloats, SimplEnv)
bind_args SimplEnv
env2 [InBndr]
bs' [Expr InBndr]
args
; (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats1 SimplFloats -> SimplFloats -> SimplFloats
`addFloats` SimplFloats
floats2, SimplEnv
env3) }
bind_args _ _ _ =
[Char] -> SDoc -> SimplM (SimplFloats, SimplEnv)
forall a. HasCallStack => [Char] -> SDoc -> a
pprPanic "bind_args" (SDoc -> SimplM (SimplFloats, SimplEnv))
-> SDoc -> SimplM (SimplFloats, SimplEnv)
forall a b. (a -> b) -> a -> b
$ DataCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr DataCon
dc SDoc -> SDoc -> SDoc
$$ [InBndr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [InBndr]
bs SDoc -> SDoc -> SDoc
$$ [Expr InBndr] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Expr InBndr]
dc_args SDoc -> SDoc -> SDoc
$$
[Char] -> SDoc
text "scrut:" SDoc -> SDoc -> SDoc
<+> Expr InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr Expr InBndr
scrut
bind_case_bndr :: SimplEnv -> SimplM (SimplFloats, SimplEnv)
bind_case_bndr env :: SimplEnv
env
| InBndr -> Bool
isDeadBinder InBndr
bndr = (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplEnv
env)
| Expr InBndr -> Bool
exprIsTrivial Expr InBndr
scrut = (SimplFloats, SimplEnv) -> SimplM (SimplFloats, SimplEnv)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env
, SimplEnv -> InBndr -> SimplSR -> SimplEnv
extendIdSubst SimplEnv
env InBndr
bndr (Expr InBndr -> Maybe Int -> SimplSR
DoneEx Expr InBndr
scrut Maybe Int
forall a. Maybe a
Nothing))
| Bool
otherwise = do { [Expr InBndr]
dc_args <- (InBndr -> SimplM (Expr InBndr))
-> [InBndr] -> SimplM [Expr InBndr]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (SimplEnv -> InBndr -> SimplM (Expr InBndr)
simplVar SimplEnv
env) [InBndr]
bs
; let con_app :: Expr InBndr
con_app = InBndr -> Expr InBndr
forall b. InBndr -> Expr b
Var (DataCon -> InBndr
dataConWorkId DataCon
dc)
Expr InBndr -> [OutType] -> Expr InBndr
forall b. Expr b -> [OutType] -> Expr b
`mkTyApps` [OutType]
dc_ty_args
Expr InBndr -> [Expr InBndr] -> Expr InBndr
forall b. Expr b -> [Expr b] -> Expr b
`mkApps` [Expr InBndr]
dc_args
; SimplEnv -> InBndr -> Expr InBndr -> SimplM (SimplFloats, SimplEnv)
simplNonRecX SimplEnv
env InBndr
bndr Expr InBndr
con_app }
missingAlt :: SimplEnv -> Id -> [InAlt] -> SimplCont
-> SimplM (SimplFloats, OutExpr)
missingAlt :: SimplEnv
-> InBndr
-> [Alt InBndr]
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
missingAlt env :: SimplEnv
env case_bndr :: InBndr
case_bndr _ cont :: SimplCont
cont
= WARN( True, text "missingAlt" <+> ppr case_bndr )
let cont_ty :: OutType
cont_ty = SimplCont -> OutType
contResultType SimplCont
cont
in OutType -> ()
seqType OutType
cont_ty ()
-> SimplM (SimplFloats, Expr InBndr)
-> SimplM (SimplFloats, Expr InBndr)
forall a b. a -> b -> b
`seq`
(SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, OutType -> Expr InBndr
mkImpossibleExpr OutType
cont_ty)
mkDupableCaseCont :: SimplEnv -> [InAlt] -> SimplCont
-> SimplM (SimplFloats, SimplCont)
mkDupableCaseCont :: SimplEnv
-> [Alt InBndr] -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCaseCont env :: SimplEnv
env alts :: [Alt InBndr]
alts cont :: SimplCont
cont
| [Alt InBndr] -> Bool
altsWouldDup [Alt InBndr]
alts = SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont SimplEnv
env SimplCont
cont
| Bool
otherwise = (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplCont
cont)
altsWouldDup :: [InAlt] -> Bool
altsWouldDup :: [Alt InBndr] -> Bool
altsWouldDup [] = Bool
False
altsWouldDup [_] = Bool
False
altsWouldDup (alt :: Alt InBndr
alt:alts :: [Alt InBndr]
alts)
| Alt InBndr -> Bool
forall a b. (a, b, Expr InBndr) -> Bool
is_bot_alt Alt InBndr
alt = [Alt InBndr] -> Bool
altsWouldDup [Alt InBndr]
alts
| Bool
otherwise = Bool -> Bool
not ((Alt InBndr -> Bool) -> [Alt InBndr] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Alt InBndr -> Bool
forall a b. (a, b, Expr InBndr) -> Bool
is_bot_alt [Alt InBndr]
alts)
where
is_bot_alt :: (a, b, Expr InBndr) -> Bool
is_bot_alt (_,_,rhs :: Expr InBndr
rhs) = Expr InBndr -> Bool
exprIsBottom Expr InBndr
rhs
mkDupableCont :: SimplEnv -> SimplCont
-> SimplM ( SimplFloats
, SimplCont)
mkDupableCont :: SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont env :: SimplEnv
env cont :: SimplCont
cont
| SimplCont -> Bool
contIsDupable SimplCont
cont
= (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, SimplCont
cont)
mkDupableCont _ (Stop {}) = [Char] -> SimplM (SimplFloats, SimplCont)
forall a. [Char] -> a
panic "mkDupableCont"
mkDupableCont env :: SimplEnv
env (CastIt ty :: Coercion
ty cont :: SimplCont
cont)
= do { (floats :: SimplFloats
floats, cont' :: SimplCont
cont') <- SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont SimplEnv
env SimplCont
cont
; (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, Coercion -> SimplCont -> SimplCont
CastIt Coercion
ty SimplCont
cont') }
mkDupableCont env :: SimplEnv
env (TickIt t :: Tickish InBndr
t cont :: SimplCont
cont)
= do { (floats :: SimplFloats
floats, cont' :: SimplCont
cont') <- SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont SimplEnv
env SimplCont
cont
; (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, Tickish InBndr -> SimplCont -> SimplCont
TickIt Tickish InBndr
t SimplCont
cont') }
mkDupableCont env :: SimplEnv
env (StrictBind { sc_bndr :: SimplCont -> InBndr
sc_bndr = InBndr
bndr, sc_bndrs :: SimplCont -> [InBndr]
sc_bndrs = [InBndr]
bndrs
, sc_body :: SimplCont -> Expr InBndr
sc_body = Expr InBndr
body, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont})
= do { let sb_env :: SimplEnv
sb_env = SimplEnv
se SimplEnv -> SimplEnv -> SimplEnv
`setInScopeFromE` SimplEnv
env
; (sb_env1 :: SimplEnv
sb_env1, bndr' :: InBndr
bndr') <- SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplBinder SimplEnv
sb_env InBndr
bndr
; (floats1 :: SimplFloats
floats1, join_inner :: Expr InBndr
join_inner) <- SimplEnv
-> [InBndr]
-> Expr InBndr
-> SimplCont
-> SimplM (SimplFloats, Expr InBndr)
simplLam SimplEnv
sb_env1 [InBndr]
bndrs Expr InBndr
body SimplCont
cont
; let join_body :: Expr InBndr
join_body = SimplFloats -> Expr InBndr -> Expr InBndr
wrapFloats SimplFloats
floats1 Expr InBndr
join_inner
res_ty :: OutType
res_ty = SimplCont -> OutType
contResultType SimplCont
cont
; (floats2 :: SimplFloats
floats2, body2 :: Expr InBndr
body2)
<- if DynFlags -> Expr InBndr -> Bool
exprIsDupable (SimplEnv -> DynFlags
seDynFlags SimplEnv
env) Expr InBndr
join_body
then (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> SimplFloats
emptyFloats SimplEnv
env, Expr InBndr
join_body)
else do { InBndr
join_bndr <- [InBndr] -> OutType -> SimplM InBndr
newJoinId [InBndr
bndr'] OutType
res_ty
; let join_call :: Expr b
join_call = Expr b -> Expr b -> Expr b
forall b. Expr b -> Expr b -> Expr b
App (InBndr -> Expr b
forall b. InBndr -> Expr b
Var InBndr
join_bndr) (InBndr -> Expr b
forall b. InBndr -> Expr b
Var InBndr
bndr')
join_rhs :: Expr InBndr
join_rhs = InBndr -> Expr InBndr -> Expr InBndr
forall b. b -> Expr b -> Expr b
Lam (InBndr -> InBndr
setOneShotLambda InBndr
bndr') Expr InBndr
join_body
join_bind :: InBind
join_bind = InBndr -> Expr InBndr -> InBind
forall b. b -> Expr b -> Bind b
NonRec InBndr
join_bndr Expr InBndr
join_rhs
floats :: SimplFloats
floats = SimplEnv -> SimplFloats
emptyFloats SimplEnv
env SimplFloats -> InBind -> SimplFloats
`extendFloats` InBind
join_bind
; (SimplFloats, Expr InBndr) -> SimplM (SimplFloats, Expr InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, Expr InBndr
forall b. Expr b
join_call) }
; (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return ( SimplFloats
floats2
, StrictBind :: DupFlag
-> InBndr
-> [InBndr]
-> Expr InBndr
-> SimplEnv
-> SimplCont
-> SimplCont
StrictBind { sc_bndr :: InBndr
sc_bndr = InBndr
bndr', sc_bndrs :: [InBndr]
sc_bndrs = []
, sc_body :: Expr InBndr
sc_body = Expr InBndr
body2
, sc_env :: SimplEnv
sc_env = SimplEnv -> SimplEnv
zapSubstEnv SimplEnv
se SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
floats2
, sc_dup :: DupFlag
sc_dup = DupFlag
OkToDup
, sc_cont :: SimplCont
sc_cont = OutType -> SimplCont
mkBoringStop OutType
res_ty } ) }
mkDupableCont env :: SimplEnv
env (StrictArg { sc_fun :: SimplCont -> ArgInfo
sc_fun = ArgInfo
info, sc_cci :: SimplCont -> CallCtxt
sc_cci = CallCtxt
cci, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
= do { (floats1 :: SimplFloats
floats1, cont' :: SimplCont
cont') <- SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont SimplEnv
env SimplCont
cont
; (floats_s :: [LetFloats]
floats_s, args' :: [ArgSpec]
args') <- (ArgSpec -> SimplM (LetFloats, ArgSpec))
-> [ArgSpec] -> SimplM ([LetFloats], [ArgSpec])
forall (m :: * -> *) a b c.
Applicative m =>
(a -> m (b, c)) -> [a] -> m ([b], [c])
mapAndUnzipM (SimplMode -> ArgSpec -> SimplM (LetFloats, ArgSpec)
makeTrivialArg (SimplEnv -> SimplMode
getMode SimplEnv
env))
(ArgInfo -> [ArgSpec]
ai_args ArgInfo
info)
; (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return ( (SimplFloats -> LetFloats -> SimplFloats)
-> SimplFloats -> [LetFloats] -> SimplFloats
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' SimplFloats -> LetFloats -> SimplFloats
addLetFloats SimplFloats
floats1 [LetFloats]
floats_s
, StrictArg :: DupFlag -> ArgInfo -> CallCtxt -> SimplCont -> SimplCont
StrictArg { sc_fun :: ArgInfo
sc_fun = ArgInfo
info { ai_args :: [ArgSpec]
ai_args = [ArgSpec]
args' }
, sc_cci :: CallCtxt
sc_cci = CallCtxt
cci
, sc_cont :: SimplCont
sc_cont = SimplCont
cont'
, sc_dup :: DupFlag
sc_dup = DupFlag
OkToDup} ) }
mkDupableCont env :: SimplEnv
env (ApplyToTy { sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont
, sc_arg_ty :: SimplCont -> OutType
sc_arg_ty = OutType
arg_ty, sc_hole_ty :: SimplCont -> OutType
sc_hole_ty = OutType
hole_ty })
= do { (floats :: SimplFloats
floats, cont' :: SimplCont
cont') <- SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont SimplEnv
env SimplCont
cont
; (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
floats, ApplyToTy :: OutType -> OutType -> SimplCont -> SimplCont
ApplyToTy { sc_cont :: SimplCont
sc_cont = SimplCont
cont'
, sc_arg_ty :: OutType
sc_arg_ty = OutType
arg_ty, sc_hole_ty :: OutType
sc_hole_ty = OutType
hole_ty }) }
mkDupableCont env :: SimplEnv
env (ApplyToVal { sc_arg :: SimplCont -> Expr InBndr
sc_arg = Expr InBndr
arg, sc_dup :: SimplCont -> DupFlag
sc_dup = DupFlag
dup
, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
=
do { (floats1 :: SimplFloats
floats1, cont' :: SimplCont
cont') <- SimplEnv -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCont SimplEnv
env SimplCont
cont
; let env' :: SimplEnv
env' = SimplEnv
env SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
floats1
; (_, se' :: SimplEnv
se', arg' :: Expr InBndr
arg') <- SimplEnv
-> DupFlag
-> SimplEnv
-> Expr InBndr
-> SimplM (DupFlag, SimplEnv, Expr InBndr)
simplArg SimplEnv
env' DupFlag
dup SimplEnv
se Expr InBndr
arg
; (let_floats2 :: LetFloats
let_floats2, arg'' :: Expr InBndr
arg'') <- SimplMode
-> TopLevelFlag
-> FastString
-> Expr InBndr
-> SimplM (LetFloats, Expr InBndr)
makeTrivial (SimplEnv -> SimplMode
getMode SimplEnv
env) TopLevelFlag
NotTopLevel ([Char] -> FastString
fsLit "karg") Expr InBndr
arg'
; let all_floats :: SimplFloats
all_floats = SimplFloats
floats1 SimplFloats -> LetFloats -> SimplFloats
`addLetFloats` LetFloats
let_floats2
; (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return ( SimplFloats
all_floats
, ApplyToVal :: DupFlag -> Expr InBndr -> SimplEnv -> SimplCont -> SimplCont
ApplyToVal { sc_arg :: Expr InBndr
sc_arg = Expr InBndr
arg''
, sc_env :: SimplEnv
sc_env = SimplEnv
se' SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
all_floats
, sc_dup :: DupFlag
sc_dup = DupFlag
OkToDup, sc_cont :: SimplCont
sc_cont = SimplCont
cont' }) }
mkDupableCont env :: SimplEnv
env (Select { sc_bndr :: SimplCont -> InBndr
sc_bndr = InBndr
case_bndr, sc_alts :: SimplCont -> [Alt InBndr]
sc_alts = [Alt InBndr]
alts
, sc_env :: SimplCont -> SimplEnv
sc_env = SimplEnv
se, sc_cont :: SimplCont -> SimplCont
sc_cont = SimplCont
cont })
=
do { Tick -> SimplM ()
tick (InBndr -> Tick
CaseOfCase InBndr
case_bndr)
; (floats :: SimplFloats
floats, alt_cont :: SimplCont
alt_cont) <- SimplEnv
-> [Alt InBndr] -> SimplCont -> SimplM (SimplFloats, SimplCont)
mkDupableCaseCont SimplEnv
env [Alt InBndr]
alts SimplCont
cont
; let alt_env :: SimplEnv
alt_env = SimplEnv
se SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
floats
; (alt_env' :: SimplEnv
alt_env', case_bndr' :: InBndr
case_bndr') <- SimplEnv -> InBndr -> SimplM (SimplEnv, InBndr)
simplBinder SimplEnv
alt_env InBndr
case_bndr
; [Alt InBndr]
alts' <- (Alt InBndr -> SimplM (Alt InBndr))
-> [Alt InBndr] -> SimplM [Alt InBndr]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (SimplEnv
-> Maybe (Expr InBndr)
-> [AltCon]
-> InBndr
-> SimplCont
-> Alt InBndr
-> SimplM (Alt InBndr)
simplAlt SimplEnv
alt_env' Maybe (Expr InBndr)
forall a. Maybe a
Nothing [] InBndr
case_bndr' SimplCont
alt_cont) [Alt InBndr]
alts
; (join_floats :: JoinFloats
join_floats, alts'' :: [Alt InBndr]
alts'') <- (JoinFloats -> Alt InBndr -> SimplM (JoinFloats, Alt InBndr))
-> JoinFloats -> [Alt InBndr] -> SimplM (JoinFloats, [Alt InBndr])
forall (m :: * -> *) acc x y.
Monad m =>
(acc -> x -> m (acc, y)) -> acc -> [x] -> m (acc, [y])
mapAccumLM (DynFlags
-> InBndr
-> JoinFloats
-> Alt InBndr
-> SimplM (JoinFloats, Alt InBndr)
mkDupableAlt (SimplEnv -> DynFlags
seDynFlags SimplEnv
env) InBndr
case_bndr')
JoinFloats
emptyJoinFloats [Alt InBndr]
alts'
; let all_floats :: SimplFloats
all_floats = SimplFloats
floats SimplFloats -> JoinFloats -> SimplFloats
`addJoinFloats` JoinFloats
join_floats
; (SimplFloats, SimplCont) -> SimplM (SimplFloats, SimplCont)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplFloats
all_floats
, Select :: DupFlag
-> InBndr -> [Alt InBndr] -> SimplEnv -> SimplCont -> SimplCont
Select { sc_dup :: DupFlag
sc_dup = DupFlag
OkToDup
, sc_bndr :: InBndr
sc_bndr = InBndr
case_bndr'
, sc_alts :: [Alt InBndr]
sc_alts = [Alt InBndr]
alts''
, sc_env :: SimplEnv
sc_env = SimplEnv -> SimplEnv
zapSubstEnv SimplEnv
se SimplEnv -> SimplFloats -> SimplEnv
`setInScopeFromF` SimplFloats
all_floats
, sc_cont :: SimplCont
sc_cont = OutType -> SimplCont
mkBoringStop (SimplCont -> OutType
contResultType SimplCont
cont) } ) }
mkDupableAlt :: DynFlags -> OutId
-> JoinFloats -> OutAlt
-> SimplM (JoinFloats, OutAlt)
mkDupableAlt :: DynFlags
-> InBndr
-> JoinFloats
-> Alt InBndr
-> SimplM (JoinFloats, Alt InBndr)
mkDupableAlt dflags :: DynFlags
dflags case_bndr :: InBndr
case_bndr jfloats :: JoinFloats
jfloats (con :: AltCon
con, bndrs' :: [InBndr]
bndrs', rhs' :: Expr InBndr
rhs')
| DynFlags -> Expr InBndr -> Bool
exprIsDupable DynFlags
dflags Expr InBndr
rhs'
= (JoinFloats, Alt InBndr) -> SimplM (JoinFloats, Alt InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (JoinFloats
jfloats, (AltCon
con, [InBndr]
bndrs', Expr InBndr
rhs'))
| Bool
otherwise
= do { let rhs_ty' :: OutType
rhs_ty' = Expr InBndr -> OutType
exprType Expr InBndr
rhs'
scrut_ty :: OutType
scrut_ty = InBndr -> OutType
idType InBndr
case_bndr
case_bndr_w_unf :: InBndr
case_bndr_w_unf
= case AltCon
con of
DEFAULT -> InBndr
case_bndr
DataAlt dc :: DataCon
dc -> InBndr -> Unfolding -> InBndr
setIdUnfolding InBndr
case_bndr Unfolding
unf
where
unf :: Unfolding
unf = Expr InBndr -> Unfolding
mkInlineUnfolding Expr InBndr
forall b. Expr b
rhs
rhs :: Expr b
rhs = DataCon -> [OutType] -> [InBndr] -> Expr b
forall b. DataCon -> [OutType] -> [InBndr] -> Expr b
mkConApp2 DataCon
dc (OutType -> [OutType]
tyConAppArgs OutType
scrut_ty) [InBndr]
bndrs'
LitAlt {} -> WARN( True, text "mkDupableAlt"
<+> ppr case_bndr <+> ppr con )
InBndr
case_bndr
final_bndrs' :: [InBndr]
final_bndrs'
| InBndr -> Bool
isDeadBinder InBndr
case_bndr = (InBndr -> Bool) -> [InBndr] -> [InBndr]
forall a. (a -> Bool) -> [a] -> [a]
filter InBndr -> Bool
abstract_over [InBndr]
bndrs'
| Bool
otherwise = [InBndr]
bndrs' [InBndr] -> [InBndr] -> [InBndr]
forall a. [a] -> [a] -> [a]
++ [InBndr
case_bndr_w_unf]
abstract_over :: InBndr -> Bool
abstract_over bndr :: InBndr
bndr
| InBndr -> Bool
isTyVar InBndr
bndr = Bool
True
| Bool
otherwise = Bool -> Bool
not (InBndr -> Bool
isDeadBinder InBndr
bndr)
final_args :: [Expr b]
final_args = [InBndr] -> [Expr b]
forall b. [InBndr] -> [Expr b]
varsToCoreExprs [InBndr]
final_bndrs'
really_final_bndrs :: [InBndr]
really_final_bndrs = (InBndr -> InBndr) -> [InBndr] -> [InBndr]
forall a b. (a -> b) -> [a] -> [b]
map InBndr -> InBndr
one_shot [InBndr]
final_bndrs'
one_shot :: InBndr -> InBndr
one_shot v :: InBndr
v | InBndr -> Bool
isId InBndr
v = InBndr -> InBndr
setOneShotLambda InBndr
v
| Bool
otherwise = InBndr
v
join_rhs :: Expr InBndr
join_rhs = [InBndr] -> Expr InBndr -> Expr InBndr
forall b. [b] -> Expr b -> Expr b
mkLams [InBndr]
really_final_bndrs Expr InBndr
rhs'
; InBndr
join_bndr <- [InBndr] -> OutType -> SimplM InBndr
newJoinId [InBndr]
final_bndrs' OutType
rhs_ty'
; let join_call :: Expr b
join_call = Expr b -> [Expr b] -> Expr b
forall b. Expr b -> [Expr b] -> Expr b
mkApps (InBndr -> Expr b
forall b. InBndr -> Expr b
Var InBndr
join_bndr) [Expr b]
forall b. [Expr b]
final_args
alt' :: (AltCon, [InBndr], Expr b)
alt' = (AltCon
con, [InBndr]
bndrs', Expr b
forall b. Expr b
join_call)
; (JoinFloats, Alt InBndr) -> SimplM (JoinFloats, Alt InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return ( JoinFloats
jfloats JoinFloats -> JoinFloats -> JoinFloats
`addJoinFlts` InBind -> JoinFloats
unitJoinFloat (InBndr -> Expr InBndr -> InBind
forall b. b -> Expr b -> Bind b
NonRec InBndr
join_bndr Expr InBndr
join_rhs)
, Alt InBndr
forall b. (AltCon, [InBndr], Expr b)
alt') }
simplLetUnfolding :: SimplEnv-> TopLevelFlag
-> MaybeJoinCont
-> InId
-> OutExpr -> OutType
-> Unfolding -> SimplM Unfolding
simplLetUnfolding :: SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> Expr InBndr
-> OutType
-> Unfolding
-> SimplM Unfolding
simplLetUnfolding env :: SimplEnv
env top_lvl :: TopLevelFlag
top_lvl cont_mb :: MaybeJoinCont
cont_mb id :: InBndr
id new_rhs :: Expr InBndr
new_rhs rhs_ty :: OutType
rhs_ty unf :: Unfolding
unf
| Unfolding -> Bool
isStableUnfolding Unfolding
unf
= SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> Unfolding
-> OutType
-> SimplM Unfolding
simplStableUnfolding SimplEnv
env TopLevelFlag
top_lvl MaybeJoinCont
cont_mb InBndr
id Unfolding
unf OutType
rhs_ty
| InBndr -> Bool
isExitJoinId InBndr
id
= Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return Unfolding
noUnfolding
| Bool
otherwise
= DynFlags
-> TopLevelFlag
-> UnfoldingSource
-> InBndr
-> Expr InBndr
-> SimplM Unfolding
mkLetUnfolding (SimplEnv -> DynFlags
seDynFlags SimplEnv
env) TopLevelFlag
top_lvl UnfoldingSource
InlineRhs InBndr
id Expr InBndr
new_rhs
mkLetUnfolding :: DynFlags -> TopLevelFlag -> UnfoldingSource
-> InId -> OutExpr -> SimplM Unfolding
mkLetUnfolding :: DynFlags
-> TopLevelFlag
-> UnfoldingSource
-> InBndr
-> Expr InBndr
-> SimplM Unfolding
mkLetUnfolding dflags :: DynFlags
dflags top_lvl :: TopLevelFlag
top_lvl src :: UnfoldingSource
src id :: InBndr
id new_rhs :: Expr InBndr
new_rhs
= Bool
is_bottoming Bool -> SimplM Unfolding -> SimplM Unfolding
forall a b. a -> b -> b
`seq`
Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return (DynFlags
-> UnfoldingSource -> Bool -> Bool -> Expr InBndr -> Unfolding
mkUnfolding DynFlags
dflags UnfoldingSource
src Bool
is_top_lvl Bool
is_bottoming Expr InBndr
new_rhs)
where
is_top_lvl :: Bool
is_top_lvl = TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
is_bottoming :: Bool
is_bottoming = InBndr -> Bool
isBottomingId InBndr
id
simplStableUnfolding :: SimplEnv -> TopLevelFlag
-> MaybeJoinCont
-> InId
-> Unfolding -> OutType -> SimplM Unfolding
simplStableUnfolding :: SimplEnv
-> TopLevelFlag
-> MaybeJoinCont
-> InBndr
-> Unfolding
-> OutType
-> SimplM Unfolding
simplStableUnfolding env :: SimplEnv
env top_lvl :: TopLevelFlag
top_lvl mb_cont :: MaybeJoinCont
mb_cont id :: InBndr
id unf :: Unfolding
unf rhs_ty :: OutType
rhs_ty
= case Unfolding
unf of
NoUnfolding -> Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return Unfolding
unf
BootUnfolding -> Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return Unfolding
unf
OtherCon {} -> Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return Unfolding
unf
DFunUnfolding { df_bndrs :: Unfolding -> [InBndr]
df_bndrs = [InBndr]
bndrs, df_con :: Unfolding -> DataCon
df_con = DataCon
con, df_args :: Unfolding -> [Expr InBndr]
df_args = [Expr InBndr]
args }
-> do { (env' :: SimplEnv
env', bndrs' :: [InBndr]
bndrs') <- SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
simplBinders SimplEnv
unf_env [InBndr]
bndrs
; [Expr InBndr]
args' <- (Expr InBndr -> SimplM (Expr InBndr))
-> [Expr InBndr] -> SimplM [Expr InBndr]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (SimplEnv -> Expr InBndr -> SimplM (Expr InBndr)
simplExpr SimplEnv
env') [Expr InBndr]
args
; Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return ([InBndr] -> DataCon -> [Expr InBndr] -> Unfolding
mkDFunUnfolding [InBndr]
bndrs' DataCon
con [Expr InBndr]
args') }
CoreUnfolding { uf_tmpl :: Unfolding -> Expr InBndr
uf_tmpl = Expr InBndr
expr, uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
guide }
| UnfoldingSource -> Bool
isStableSource UnfoldingSource
src
-> do { Expr InBndr
expr' <- case MaybeJoinCont
mb_cont of
Just cont :: SimplCont
cont -> SimplEnv
-> InBndr -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplJoinRhs SimplEnv
unf_env InBndr
id Expr InBndr
expr SimplCont
cont
Nothing -> SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC SimplEnv
unf_env Expr InBndr
expr (OutType -> SimplCont
mkBoringStop OutType
rhs_ty)
; case UnfoldingGuidance
guide of
UnfWhen { ug_arity :: UnfoldingGuidance -> Int
ug_arity = Int
arity
, ug_unsat_ok :: UnfoldingGuidance -> Bool
ug_unsat_ok = Bool
sat_ok
, ug_boring_ok :: UnfoldingGuidance -> Bool
ug_boring_ok = Bool
boring_ok
}
-> let guide' :: UnfoldingGuidance
guide' =
UnfWhen :: Int -> Bool -> Bool -> UnfoldingGuidance
UnfWhen { ug_arity :: Int
ug_arity = Int
arity
, ug_unsat_ok :: Bool
ug_unsat_ok = Bool
sat_ok
, ug_boring_ok :: Bool
ug_boring_ok =
Bool
boring_ok Bool -> Bool -> Bool
|| Expr InBndr -> Bool
inlineBoringOk Expr InBndr
expr'
}
in Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return (UnfoldingSource
-> Bool -> Expr InBndr -> UnfoldingGuidance -> Unfolding
mkCoreUnfolding UnfoldingSource
src Bool
is_top_lvl Expr InBndr
expr' UnfoldingGuidance
guide')
_other :: UnfoldingGuidance
_other
-> DynFlags
-> TopLevelFlag
-> UnfoldingSource
-> InBndr
-> Expr InBndr
-> SimplM Unfolding
mkLetUnfolding DynFlags
dflags TopLevelFlag
top_lvl UnfoldingSource
src InBndr
id Expr InBndr
expr' }
| Bool
otherwise -> Unfolding -> SimplM Unfolding
forall (m :: * -> *) a. Monad m => a -> m a
return Unfolding
noUnfolding
where
dflags :: DynFlags
dflags = SimplEnv -> DynFlags
seDynFlags SimplEnv
env
is_top_lvl :: Bool
is_top_lvl = TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl
act :: Activation
act = InBndr -> Activation
idInlineActivation InBndr
id
unf_env :: SimplEnv
unf_env = (SimplMode -> SimplMode) -> SimplEnv -> SimplEnv
updMode (Activation -> SimplMode -> SimplMode
updModeForStableUnfoldings Activation
act) SimplEnv
env
addBndrRules :: SimplEnv -> InBndr -> OutBndr
-> MaybeJoinCont
-> SimplM (SimplEnv, OutBndr)
addBndrRules :: SimplEnv
-> InBndr -> InBndr -> MaybeJoinCont -> SimplM (SimplEnv, InBndr)
addBndrRules env :: SimplEnv
env in_id :: InBndr
in_id out_id :: InBndr
out_id mb_cont :: MaybeJoinCont
mb_cont
| [CoreRule] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreRule]
old_rules
= (SimplEnv, InBndr) -> SimplM (SimplEnv, InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv
env, InBndr
out_id)
| Bool
otherwise
= do { [CoreRule]
new_rules <- SimplEnv
-> Maybe InBndr -> [CoreRule] -> MaybeJoinCont -> SimplM [CoreRule]
simplRules SimplEnv
env (InBndr -> Maybe InBndr
forall a. a -> Maybe a
Just InBndr
out_id) [CoreRule]
old_rules MaybeJoinCont
mb_cont
; let final_id :: InBndr
final_id = InBndr
out_id InBndr -> RuleInfo -> InBndr
`setIdSpecialisation` [CoreRule] -> RuleInfo
mkRuleInfo [CoreRule]
new_rules
; (SimplEnv, InBndr) -> SimplM (SimplEnv, InBndr)
forall (m :: * -> *) a. Monad m => a -> m a
return (SimplEnv -> InBndr -> SimplEnv
modifyInScope SimplEnv
env InBndr
final_id, InBndr
final_id) }
where
old_rules :: [CoreRule]
old_rules = RuleInfo -> [CoreRule]
ruleInfoRules (InBndr -> RuleInfo
idSpecialisation InBndr
in_id)
simplRules :: SimplEnv -> Maybe OutId -> [CoreRule]
-> MaybeJoinCont -> SimplM [CoreRule]
simplRules :: SimplEnv
-> Maybe InBndr -> [CoreRule] -> MaybeJoinCont -> SimplM [CoreRule]
simplRules env :: SimplEnv
env mb_new_id :: Maybe InBndr
mb_new_id rules :: [CoreRule]
rules mb_cont :: MaybeJoinCont
mb_cont
= (CoreRule -> SimplM CoreRule) -> [CoreRule] -> SimplM [CoreRule]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM CoreRule -> SimplM CoreRule
simpl_rule [CoreRule]
rules
where
simpl_rule :: CoreRule -> SimplM CoreRule
simpl_rule rule :: CoreRule
rule@(BuiltinRule {})
= CoreRule -> SimplM CoreRule
forall (m :: * -> *) a. Monad m => a -> m a
return CoreRule
rule
simpl_rule rule :: CoreRule
rule@(Rule { ru_bndrs :: CoreRule -> [InBndr]
ru_bndrs = [InBndr]
bndrs, ru_args :: CoreRule -> [Expr InBndr]
ru_args = [Expr InBndr]
args
, ru_fn :: CoreRule -> Name
ru_fn = Name
fn_name, ru_rhs :: CoreRule -> Expr InBndr
ru_rhs = Expr InBndr
rhs })
= do { (env' :: SimplEnv
env', bndrs' :: [InBndr]
bndrs') <- SimplEnv -> [InBndr] -> SimplM (SimplEnv, [InBndr])
simplBinders SimplEnv
env [InBndr]
bndrs
; let rhs_ty :: OutType
rhs_ty = SimplEnv -> OutType -> OutType
substTy SimplEnv
env' (Expr InBndr -> OutType
exprType Expr InBndr
rhs)
rhs_cont :: SimplCont
rhs_cont = case MaybeJoinCont
mb_cont of
Nothing -> OutType -> SimplCont
mkBoringStop OutType
rhs_ty
Just cont :: SimplCont
cont -> ASSERT2( join_ok, bad_join_msg )
SimplCont
cont
rule_env :: SimplEnv
rule_env = (SimplMode -> SimplMode) -> SimplEnv -> SimplEnv
updMode SimplMode -> SimplMode
updModeForRules SimplEnv
env'
fn_name' :: Name
fn_name' = case Maybe InBndr
mb_new_id of
Just id :: InBndr
id -> InBndr -> Name
idName InBndr
id
Nothing -> Name
fn_name
join_ok :: Bool
join_ok = case Maybe InBndr
mb_new_id of
Just id :: InBndr
id | Just join_arity :: Int
join_arity <- InBndr -> Maybe Int
isJoinId_maybe InBndr
id
-> [Expr InBndr] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Expr InBndr]
args Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
join_arity
_ -> Bool
False
bad_join_msg :: SDoc
bad_join_msg = [SDoc] -> SDoc
vcat [ Maybe InBndr -> SDoc
forall a. Outputable a => a -> SDoc
ppr Maybe InBndr
mb_new_id, CoreRule -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreRule
rule
, Maybe (Maybe Int) -> SDoc
forall a. Outputable a => a -> SDoc
ppr ((InBndr -> Maybe Int) -> Maybe InBndr -> Maybe (Maybe Int)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap InBndr -> Maybe Int
isJoinId_maybe Maybe InBndr
mb_new_id) ]
; [Expr InBndr]
args' <- (Expr InBndr -> SimplM (Expr InBndr))
-> [Expr InBndr] -> SimplM [Expr InBndr]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (SimplEnv -> Expr InBndr -> SimplM (Expr InBndr)
simplExpr SimplEnv
rule_env) [Expr InBndr]
args
; Expr InBndr
rhs' <- SimplEnv -> Expr InBndr -> SimplCont -> SimplM (Expr InBndr)
simplExprC SimplEnv
rule_env Expr InBndr
rhs SimplCont
rhs_cont
; CoreRule -> SimplM CoreRule
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreRule
rule { ru_bndrs :: [InBndr]
ru_bndrs = [InBndr]
bndrs'
, ru_fn :: Name
ru_fn = Name
fn_name'
, ru_args :: [Expr InBndr]
ru_args = [Expr InBndr]
args'
, ru_rhs :: Expr InBndr
ru_rhs = Expr InBndr
rhs' }) }