{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
module GHC.CoreToStg.Prep
( CorePrepConfig (..)
, CorePrepPgmConfig (..)
, corePrepPgm
, corePrepExpr
, mkConvertNumLiteral
)
where
import GHC.Prelude
import GHC.Platform
import GHC.Driver.Flags
import GHC.Tc.Utils.Env
import GHC.Unit
import GHC.Builtin.Names
import GHC.Builtin.Types
import GHC.Core.Utils
import GHC.Core.Opt.Arity
import GHC.Core.Lint ( EndPassConfig(..), endPassIO )
import GHC.Core
import GHC.Core.Subst
import GHC.Core.Make hiding( FloatBind(..) )
import GHC.Core.Type
import GHC.Core.Coercion
import GHC.Core.TyCon
import GHC.Core.DataCon
import GHC.Core.Opt.OccurAnal
import GHC.Data.Maybe
import GHC.Data.OrdList
import GHC.Data.FastString
import GHC.Data.Graph.UnVar
import GHC.Utils.Error
import GHC.Utils.Misc
import GHC.Utils.Panic
import GHC.Utils.Outputable
import GHC.Utils.Monad ( mapAccumLM )
import GHC.Utils.Logger
import GHC.Types.Demand
import GHC.Types.Var
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Id.Make ( realWorldPrimId )
import GHC.Types.Basic
import GHC.Types.Name ( Name, NamedThing(..), nameSrcSpan, isInternalName )
import GHC.Types.SrcLoc ( SrcSpan(..), realSrcLocSpan, mkRealSrcLoc )
import GHC.Types.Literal
import GHC.Types.Tickish
import GHC.Types.TyThing
import GHC.Types.Unique.Supply
import Data.List ( unfoldr )
import Control.Monad
type CpeArg = CoreExpr
type CpeApp = CoreExpr
type CpeBody = CoreExpr
type CpeRhs = CoreExpr
data CorePrepPgmConfig = CorePrepPgmConfig
{ CorePrepPgmConfig -> EndPassConfig
cpPgm_endPassConfig :: !EndPassConfig
, CorePrepPgmConfig -> Bool
cpPgm_generateDebugInfo :: !Bool
}
corePrepPgm :: Logger
-> CorePrepConfig
-> CorePrepPgmConfig
-> Module -> ModLocation -> CoreProgram -> [TyCon]
-> IO CoreProgram
corePrepPgm :: Logger
-> CorePrepConfig
-> CorePrepPgmConfig
-> Module
-> ModLocation
-> CoreProgram
-> [TyCon]
-> IO CoreProgram
corePrepPgm Logger
logger CorePrepConfig
cp_cfg CorePrepPgmConfig
pgm_cfg
Module
this_mod ModLocation
mod_loc CoreProgram
binds [TyCon]
data_tycons =
Logger
-> SDoc -> (CoreProgram -> ()) -> IO CoreProgram -> IO CoreProgram
forall (m :: * -> *) a.
MonadIO m =>
Logger -> SDoc -> (a -> ()) -> m a -> m a
withTiming Logger
logger
(String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"CorePrep"SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+>SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
brackets (Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
this_mod))
(\CoreProgram
a -> CoreProgram
a CoreProgram -> () -> ()
forall a b. [a] -> b -> b
`seqList` ()) (IO CoreProgram -> IO CoreProgram)
-> IO CoreProgram -> IO CoreProgram
forall a b. (a -> b) -> a -> b
$ do
us <- Char -> IO UniqSupply
mkSplitUniqSupply Char
's'
let initialCorePrepEnv = CorePrepConfig -> CorePrepEnv
mkInitialCorePrepEnv CorePrepConfig
cp_cfg
let
implicit_binds = Bool -> ModLocation -> [TyCon] -> CoreProgram
mkDataConWorkers
(CorePrepPgmConfig -> Bool
cpPgm_generateDebugInfo CorePrepPgmConfig
pgm_cfg)
ModLocation
mod_loc [TyCon]
data_tycons
binds_out = UniqSupply -> UniqSM CoreProgram -> CoreProgram
forall a. UniqSupply -> UniqSM a -> a
initUs_ UniqSupply
us (UniqSM CoreProgram -> CoreProgram)
-> UniqSM CoreProgram -> CoreProgram
forall a b. (a -> b) -> a -> b
$ do
floats1 <- CorePrepEnv -> CoreProgram -> UniqSM Floats
corePrepTopBinds CorePrepEnv
initialCorePrepEnv CoreProgram
binds
floats2 <- corePrepTopBinds initialCorePrepEnv implicit_binds
return (deFloatTop (floats1 `zipFloats` floats2))
endPassIO logger (cpPgm_endPassConfig pgm_cfg)
binds_out []
return binds_out
corePrepExpr :: Logger -> CorePrepConfig -> CoreExpr -> IO CoreExpr
corePrepExpr :: Logger -> CorePrepConfig -> CpeRhs -> IO CpeRhs
corePrepExpr Logger
logger CorePrepConfig
config CpeRhs
expr = do
Logger -> SDoc -> (CpeRhs -> ()) -> IO CpeRhs -> IO CpeRhs
forall (m :: * -> *) a.
MonadIO m =>
Logger -> SDoc -> (a -> ()) -> m a -> m a
withTiming Logger
logger (String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"CorePrep [expr]") (\CpeRhs
e -> CpeRhs
e CpeRhs -> () -> ()
forall a b. a -> b -> b
`seq` ()) (IO CpeRhs -> IO CpeRhs) -> IO CpeRhs -> IO CpeRhs
forall a b. (a -> b) -> a -> b
$ do
us <- Char -> IO UniqSupply
mkSplitUniqSupply Char
's'
let initialCorePrepEnv = CorePrepConfig -> CorePrepEnv
mkInitialCorePrepEnv CorePrepConfig
config
let new_expr = UniqSupply -> UniqSM CpeRhs -> CpeRhs
forall a. UniqSupply -> UniqSM a -> a
initUs_ UniqSupply
us (CorePrepEnv -> CpeRhs -> UniqSM CpeRhs
cpeBodyNF CorePrepEnv
initialCorePrepEnv CpeRhs
expr)
putDumpFileMaybe logger Opt_D_dump_prep "CorePrep" FormatCore (ppr new_expr)
return new_expr
corePrepTopBinds :: CorePrepEnv -> [CoreBind] -> UniqSM Floats
corePrepTopBinds :: CorePrepEnv -> CoreProgram -> UniqSM Floats
corePrepTopBinds CorePrepEnv
initialCorePrepEnv CoreProgram
binds
= CorePrepEnv -> CoreProgram -> UniqSM Floats
go CorePrepEnv
initialCorePrepEnv CoreProgram
binds
where
go :: CorePrepEnv -> CoreProgram -> UniqSM Floats
go CorePrepEnv
_ [] = Floats -> UniqSM Floats
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return Floats
emptyFloats
go CorePrepEnv
env (CoreBind
bind : CoreProgram
binds) = do (env', floats, maybe_new_bind)
<- TopLevelFlag
-> CorePrepEnv
-> CoreBind
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
cpeBind TopLevelFlag
TopLevel CorePrepEnv
env CoreBind
bind
massert (isNothing maybe_new_bind)
floatss <- go env' binds
return (floats `zipFloats` floatss)
mkDataConWorkers :: Bool -> ModLocation -> [TyCon] -> [CoreBind]
mkDataConWorkers :: Bool -> ModLocation -> [TyCon] -> CoreProgram
mkDataConWorkers Bool
generate_debug_info ModLocation
mod_loc [TyCon]
data_tycons
= [ InVar -> CpeRhs -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec InVar
id (Name -> CpeRhs -> CpeRhs
tick_it (DataCon -> Name
forall a. NamedThing a => a -> Name
getName DataCon
data_con) (InVar -> CpeRhs
forall b. InVar -> Expr b
Var InVar
id))
| TyCon
tycon <- [TyCon]
data_tycons,
DataCon
data_con <- TyCon -> [DataCon]
tyConDataCons TyCon
tycon,
let id :: InVar
id = DataCon -> InVar
dataConWorkId DataCon
data_con
]
where
tick_it :: Name -> CpeRhs -> CpeRhs
tick_it Name
name
| Bool -> Bool
not Bool
generate_debug_info = CpeRhs -> CpeRhs
forall a. a -> a
id
| RealSrcSpan RealSrcSpan
span Maybe BufSpan
_ <- Name -> SrcSpan
nameSrcSpan Name
name = RealSrcSpan -> CpeRhs -> CpeRhs
tick RealSrcSpan
span
| Just String
file <- ModLocation -> Maybe String
ml_hs_file ModLocation
mod_loc = RealSrcSpan -> CpeRhs -> CpeRhs
tick (String -> RealSrcSpan
span1 String
file)
| Bool
otherwise = RealSrcSpan -> CpeRhs -> CpeRhs
tick (String -> RealSrcSpan
span1 String
"???")
where tick :: RealSrcSpan -> CpeRhs -> CpeRhs
tick RealSrcSpan
span = CoreTickish -> CpeRhs -> CpeRhs
forall b. CoreTickish -> Expr b -> Expr b
Tick (CoreTickish -> CpeRhs -> CpeRhs)
-> CoreTickish -> CpeRhs -> CpeRhs
forall a b. (a -> b) -> a -> b
$ RealSrcSpan -> LexicalFastString -> CoreTickish
forall (pass :: TickishPass).
RealSrcSpan -> LexicalFastString -> GenTickish pass
SourceNote RealSrcSpan
span (LexicalFastString -> CoreTickish)
-> LexicalFastString -> CoreTickish
forall a b. (a -> b) -> a -> b
$
FastString -> LexicalFastString
LexicalFastString (FastString -> LexicalFastString)
-> FastString -> LexicalFastString
forall a b. (a -> b) -> a -> b
$ String -> FastString
mkFastString (String -> FastString) -> String -> FastString
forall a b. (a -> b) -> a -> b
$ SDocContext -> SDoc -> String
renderWithContext SDocContext
defaultSDocContext (SDoc -> String) -> SDoc -> String
forall a b. (a -> b) -> a -> b
$ Name -> SDoc
forall a. Outputable a => a -> SDoc
ppr Name
name
span1 :: String -> RealSrcSpan
span1 String
file = RealSrcLoc -> RealSrcSpan
realSrcLocSpan (RealSrcLoc -> RealSrcSpan) -> RealSrcLoc -> RealSrcSpan
forall a b. (a -> b) -> a -> b
$ FastString -> Int -> Int -> RealSrcLoc
mkRealSrcLoc (String -> FastString
mkFastString String
file) Int
1 Int
1
cpeBind :: TopLevelFlag -> CorePrepEnv -> CoreBind
-> UniqSM (CorePrepEnv,
Floats,
Maybe CoreBind)
cpeBind :: TopLevelFlag
-> CorePrepEnv
-> CoreBind
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
cpeBind TopLevelFlag
top_lvl CorePrepEnv
env (NonRec InVar
bndr CpeRhs
rhs)
| Bool -> Bool
not (InVar -> Bool
isJoinId InVar
bndr)
= do { (env1, bndr1) <- CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, InVar)
cpCloneBndr CorePrepEnv
env InVar
bndr
; let dmd = InVar -> Demand
idDemandInfo InVar
bndr
is_unlifted = HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType (InVar -> Type
idType InVar
bndr)
; (floats, rhs1) <- cpePair top_lvl NonRecursive
dmd is_unlifted
env bndr1 rhs
; let triv_rhs = CpeRhs -> Bool
exprIsTrivial CpeRhs
rhs1
env2 | Bool
triv_rhs = CorePrepEnv -> InVar -> CpeRhs -> CorePrepEnv
extendCorePrepEnvExpr CorePrepEnv
env1 InVar
bndr CpeRhs
rhs1
| Bool
otherwise = CorePrepEnv
env1
floats1 | Bool
triv_rhs, Name -> Bool
isInternalName (InVar -> Name
idName InVar
bndr)
= Floats
floats
| Bool
otherwise
= Floats -> FloatingBind -> Floats
snocFloat Floats
floats FloatingBind
new_float
new_float = CorePrepEnv -> Demand -> Bool -> InVar -> CpeRhs -> FloatingBind
mkNonRecFloat CorePrepEnv
env Demand
dmd Bool
is_unlifted InVar
bndr1 CpeRhs
rhs1
; return (env2, floats1, Nothing) }
| Bool
otherwise
= Bool
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
forall a. HasCallStack => Bool -> a -> a
assert (Bool -> Bool
not (TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl)) (UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind))
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
forall a b. (a -> b) -> a -> b
$
do { (_, bndr1) <- CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, InVar)
cpCloneBndr CorePrepEnv
env InVar
bndr
; (bndr2, rhs1) <- cpeJoinPair env bndr1 rhs
; return (extendCorePrepEnv env bndr bndr2,
emptyFloats,
Just (NonRec bndr2 rhs1)) }
cpeBind TopLevelFlag
top_lvl CorePrepEnv
env (Rec [(InVar, CpeRhs)]
pairs)
| Bool -> Bool
not (InVar -> Bool
isJoinId ([InVar] -> InVar
forall a. HasCallStack => [a] -> a
head [InVar]
bndrs))
= do { (env, bndrs1) <- CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [InVar])
cpCloneBndrs CorePrepEnv
env [InVar]
bndrs
; let env' = CorePrepEnv -> [InVar] -> CorePrepEnv
enterRecGroupRHSs CorePrepEnv
env [InVar]
bndrs1
; stuff <- zipWithM (cpePair top_lvl Recursive topDmd False env')
bndrs1 rhss
; let (zipManyFloats -> floats, rhss1) = unzip stuff
is_lit (Float (NonRec InVar
_ CpeRhs
rhs) BindInfo
CaseBound FloatInfo
TopLvlFloatable) = CpeRhs -> Bool
exprIsTickedString CpeRhs
rhs
is_lit FloatingBind
_ = Bool
False
(string_floats, top) = partitionOL is_lit (fs_binds floats)
floats' = Floats
floats { fs_binds = top }
all_pairs = (FloatingBind -> [(InVar, CpeRhs)] -> [(InVar, CpeRhs)])
-> [(InVar, CpeRhs)] -> OrdList FloatingBind -> [(InVar, CpeRhs)]
forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL FloatingBind -> [(InVar, CpeRhs)] -> [(InVar, CpeRhs)]
add_float ([InVar]
bndrs1 [InVar] -> [CpeRhs] -> [(InVar, CpeRhs)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [CpeRhs]
rhss1) (Floats -> OrdList FloatingBind
getFloats Floats
floats')
; return (extendCorePrepEnvList env (bndrs `zip` bndrs1),
snocFloat (emptyFloats { fs_binds = string_floats })
(Float (Rec all_pairs) LetBound TopLvlFloatable),
Nothing) }
| Bool
otherwise
= do { (env, bndrs1) <- CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [InVar])
cpCloneBndrs CorePrepEnv
env [InVar]
bndrs
; let env' = CorePrepEnv -> [InVar] -> CorePrepEnv
enterRecGroupRHSs CorePrepEnv
env [InVar]
bndrs1
; pairs1 <- zipWithM (cpeJoinPair env') bndrs1 rhss
; let bndrs2 = ((InVar, CpeRhs) -> InVar) -> [(InVar, CpeRhs)] -> [InVar]
forall a b. (a -> b) -> [a] -> [b]
map (InVar, CpeRhs) -> InVar
forall a b. (a, b) -> a
fst [(InVar, CpeRhs)]
pairs1
; return (extendCorePrepEnvList env (bndrs `zip` bndrs2),
emptyFloats,
Just (Rec pairs1)) }
where
([InVar]
bndrs, [CpeRhs]
rhss) = [(InVar, CpeRhs)] -> ([InVar], [CpeRhs])
forall a b. [(a, b)] -> ([a], [b])
unzip [(InVar, CpeRhs)]
pairs
add_float :: FloatingBind -> [(InVar, CpeRhs)] -> [(InVar, CpeRhs)]
add_float (Float CoreBind
bind BindInfo
bound FloatInfo
_) [(InVar, CpeRhs)]
prs2
| BindInfo
bound BindInfo -> BindInfo -> Bool
forall a. Eq a => a -> a -> Bool
/= BindInfo
CaseBound
Bool -> Bool -> Bool
|| (InVar -> Bool) -> [InVar] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all (Type -> Bool
definitelyLiftedType (Type -> Bool) -> (InVar -> Type) -> InVar -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InVar -> Type
idType) (CoreBind -> [InVar]
forall b. Bind b -> [b]
bindersOf CoreBind
bind)
= case CoreBind
bind of
NonRec InVar
x CpeRhs
e -> (InVar
x,CpeRhs
e) (InVar, CpeRhs) -> [(InVar, CpeRhs)] -> [(InVar, CpeRhs)]
forall a. a -> [a] -> [a]
: [(InVar, CpeRhs)]
prs2
Rec [(InVar, CpeRhs)]
prs1 -> [(InVar, CpeRhs)]
prs1 [(InVar, CpeRhs)] -> [(InVar, CpeRhs)] -> [(InVar, CpeRhs)]
forall a. [a] -> [a] -> [a]
++ [(InVar, CpeRhs)]
prs2
add_float FloatingBind
f [(InVar, CpeRhs)]
_ = String -> SDoc -> [(InVar, CpeRhs)]
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"cpeBind" (FloatingBind -> SDoc
forall a. Outputable a => a -> SDoc
ppr FloatingBind
f)
cpePair :: TopLevelFlag -> RecFlag -> Demand -> Bool
-> CorePrepEnv -> OutId -> CoreExpr
-> UniqSM (Floats, CpeRhs)
cpePair :: TopLevelFlag
-> RecFlag
-> Demand
-> Bool
-> CorePrepEnv
-> InVar
-> CpeRhs
-> UniqSM (Floats, CpeRhs)
cpePair TopLevelFlag
top_lvl RecFlag
is_rec Demand
dmd Bool
is_unlifted CorePrepEnv
env InVar
bndr CpeRhs
rhs
= Bool -> UniqSM (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. HasCallStack => Bool -> a -> a
assert (Bool -> Bool
not (InVar -> Bool
isJoinId InVar
bndr)) (UniqSM (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs))
-> UniqSM (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a b. (a -> b) -> a -> b
$
do { (floats1, rhs1) <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env CpeRhs
rhs
; let dec = Floats -> CpeRhs -> FloatDecision
want_float_from_rhs Floats
floats1 CpeRhs
rhs1
; (floats2, rhs2) <- executeFloatDecision dec floats1 rhs1
; (floats3, rhs3)
<- if manifestArity rhs1 <= arity
then return (floats2, cpeEtaExpand arity rhs2)
else warnPprTrace True "CorePrep: silly extra arguments:" (ppr bndr) $
(do { v <- newVar (idType bndr)
; let float = CorePrepEnv -> Demand -> Bool -> InVar -> CpeRhs -> FloatingBind
mkNonRecFloat CorePrepEnv
env Demand
topDmd Bool
False InVar
v CpeRhs
rhs2
; return ( snocFloat floats2 float
, cpeEtaExpand arity (Var v)) })
; let (floats4, rhs4) = wrapTicks floats3 rhs3
; return (floats4, rhs4) }
where
arity :: Int
arity = InVar -> Int
idArity InVar
bndr
want_float_from_rhs :: Floats -> CpeRhs -> FloatDecision
want_float_from_rhs Floats
floats CpeRhs
rhs
| TopLevelFlag -> Bool
isTopLevel TopLevelFlag
top_lvl = Floats -> FloatDecision
wantFloatTop Floats
floats
| Bool
otherwise = RecFlag -> Demand -> Bool -> Floats -> CpeRhs -> FloatDecision
wantFloatLocal RecFlag
is_rec Demand
dmd Bool
is_unlifted Floats
floats CpeRhs
rhs
cpeJoinPair :: CorePrepEnv -> JoinId -> CoreExpr
-> UniqSM (JoinId, CpeRhs)
cpeJoinPair :: CorePrepEnv -> InVar -> CpeRhs -> UniqSM (InVar, CpeRhs)
cpeJoinPair CorePrepEnv
env InVar
bndr CpeRhs
rhs
= Bool -> UniqSM (InVar, CpeRhs) -> UniqSM (InVar, CpeRhs)
forall a. HasCallStack => Bool -> a -> a
assert (InVar -> Bool
isJoinId InVar
bndr) (UniqSM (InVar, CpeRhs) -> UniqSM (InVar, CpeRhs))
-> UniqSM (InVar, CpeRhs) -> UniqSM (InVar, CpeRhs)
forall a b. (a -> b) -> a -> b
$
do { let JoinPoint Int
join_arity = InVar -> JoinPointHood
idJoinPointHood InVar
bndr
([InVar]
bndrs, CpeRhs
body) = Int -> CpeRhs -> ([InVar], CpeRhs)
forall b. Int -> Expr b -> ([b], Expr b)
collectNBinders Int
join_arity CpeRhs
rhs
; (env', bndrs') <- CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [InVar])
cpCloneBndrs CorePrepEnv
env [InVar]
bndrs
; body' <- cpeBodyNF env' body
; let rhs' = [InVar] -> CpeRhs -> CpeRhs
mkCoreLams [InVar]
bndrs' CpeRhs
body'
bndr' = InVar
bndr InVar -> Unfolding -> InVar
`setIdUnfolding` Unfolding
evaldUnfolding
InVar -> Int -> InVar
`setIdArity` (InVar -> Bool) -> [InVar] -> Int
forall a. (a -> Bool) -> [a] -> Int
count InVar -> Bool
isId [InVar]
bndrs
; return (bndr', rhs') }
cpeRhsE :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeRhs)
cpeRhsE :: CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env (Type Type
ty)
= (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
emptyFloats, Type -> CpeRhs
forall b. Type -> Expr b
Type (CorePrepEnv -> Type -> Type
cpSubstTy CorePrepEnv
env Type
ty))
cpeRhsE CorePrepEnv
env (Coercion Coercion
co)
= (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
emptyFloats, Coercion -> CpeRhs
forall b. Coercion -> Expr b
Coercion (CorePrepEnv -> Coercion -> Coercion
cpSubstCo CorePrepEnv
env Coercion
co))
cpeRhsE CorePrepEnv
env expr :: CpeRhs
expr@(Lit (LitNumber LitNumType
nt Integer
i))
= case CorePrepConfig -> LitNumType -> Integer -> Maybe CpeRhs
cp_convertNumLit (CorePrepEnv -> CorePrepConfig
cpe_config CorePrepEnv
env) LitNumType
nt Integer
i of
Maybe CpeRhs
Nothing -> (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
emptyFloats, CpeRhs
expr)
Just CpeRhs
e -> CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env CpeRhs
e
cpeRhsE CorePrepEnv
_env expr :: CpeRhs
expr@(Lit {}) = (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
emptyFloats, CpeRhs
expr)
cpeRhsE CorePrepEnv
env expr :: CpeRhs
expr@(Var {}) = CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeApp CorePrepEnv
env CpeRhs
expr
cpeRhsE CorePrepEnv
env expr :: CpeRhs
expr@(App {}) = CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeApp CorePrepEnv
env CpeRhs
expr
cpeRhsE CorePrepEnv
env (Let CoreBind
bind CpeRhs
body)
= do { (env', bind_floats, maybe_bind') <- TopLevelFlag
-> CorePrepEnv
-> CoreBind
-> UniqSM (CorePrepEnv, Floats, Maybe CoreBind)
cpeBind TopLevelFlag
NotTopLevel CorePrepEnv
env CoreBind
bind
; (body_floats, body') <- cpeRhsE env' body
; let expr' = case Maybe CoreBind
maybe_bind' of Just CoreBind
bind' -> CoreBind -> CpeRhs -> CpeRhs
forall b. Bind b -> Expr b -> Expr b
Let CoreBind
bind' CpeRhs
body'
Maybe CoreBind
Nothing -> CpeRhs
body'
; return (bind_floats `appFloats` body_floats, expr') }
cpeRhsE CorePrepEnv
env (Tick CoreTickish
tickish CpeRhs
expr)
| CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreTickish
tickish
= do { (floats, body) <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env CpeRhs
expr
; return (FloatTick tickish `consFloat` floats, body) }
| Bool
otherwise
= do { body <- CorePrepEnv -> CpeRhs -> UniqSM CpeRhs
cpeBodyNF CorePrepEnv
env CpeRhs
expr
; return (emptyFloats, mkTick tickish' body) }
where
tickish' :: CoreTickish
tickish' | Breakpoint XBreakpoint 'TickishPassCore
ext Int
n [XTickishId 'TickishPassCore]
fvs Module
modl <- CoreTickish
tickish
= XBreakpoint 'TickishPassCore
-> Int -> [XTickishId 'TickishPassCore] -> Module -> CoreTickish
forall (pass :: TickishPass).
XBreakpoint pass
-> Int -> [XTickishId pass] -> Module -> GenTickish pass
Breakpoint XBreakpoint 'TickishPassCore
ext Int
n ((InVar -> InVar) -> [InVar] -> [InVar]
forall a b. (a -> b) -> [a] -> [b]
map (HasDebugCallStack => CpeRhs -> InVar
CpeRhs -> InVar
getIdFromTrivialExpr (CpeRhs -> InVar) -> (InVar -> CpeRhs) -> InVar -> InVar
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CorePrepEnv -> InVar -> CpeRhs
lookupCorePrepEnv CorePrepEnv
env) [InVar]
[XTickishId 'TickishPassCore]
fvs) Module
modl
| Bool
otherwise
= CoreTickish
tickish
cpeRhsE CorePrepEnv
env (Cast CpeRhs
expr Coercion
co)
= do { (floats, expr') <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env CpeRhs
expr
; return (floats, Cast expr' (cpSubstCo env co)) }
cpeRhsE CorePrepEnv
env expr :: CpeRhs
expr@(Lam {})
= do { let ([InVar]
bndrs,CpeRhs
body) = CpeRhs -> ([InVar], CpeRhs)
forall b. Expr b -> ([b], Expr b)
collectBinders CpeRhs
expr
; (env', bndrs') <- CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [InVar])
cpCloneBndrs CorePrepEnv
env [InVar]
bndrs
; body' <- cpeBodyNF env' body
; return (emptyFloats, mkLams bndrs' body') }
cpeRhsE CorePrepEnv
env (Case CpeRhs
scrut InVar
bndr Type
_ alts :: [Alt InVar]
alts@[Alt AltCon
con [InVar
covar] CpeRhs
_])
| Just CpeRhs
rhs <- CpeRhs -> InVar -> [Alt InVar] -> Maybe CpeRhs
isUnsafeEqualityCase CpeRhs
scrut InVar
bndr [Alt InVar]
alts
= do { (floats_scrut, scrut) <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeBody CorePrepEnv
env CpeRhs
scrut
; (env, bndr') <- cpCloneBndr env bndr
; (env, covar') <- cpCloneCoVarBndr env covar
; (floats_rhs, rhs) <- cpeBody env rhs
; let case_float = CpeRhs -> InVar -> AltCon -> [InVar] -> FloatingBind
UnsafeEqualityCase CpeRhs
scrut InVar
bndr' AltCon
con [InVar
covar']
floats = Floats -> FloatingBind -> Floats
snocFloat Floats
floats_scrut FloatingBind
case_float Floats -> Floats -> Floats
`appFloats` Floats
floats_rhs
; return (floats, rhs) }
cpeRhsE CorePrepEnv
env (Case CpeRhs
scrut InVar
bndr Type
ty [Alt InVar]
alts)
= do { (floats, scrut') <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeBody CorePrepEnv
env CpeRhs
scrut
; (env', bndr2) <- cpCloneBndr env bndr
; let alts'
| CorePrepConfig -> Bool
cp_catchNonexhaustiveCases (CorePrepConfig -> Bool) -> CorePrepConfig -> Bool
forall a b. (a -> b) -> a -> b
$ CorePrepEnv -> CorePrepConfig
cpe_config CorePrepEnv
env
, Bool -> Bool
not ([Alt InVar] -> Bool
forall b. [Alt b] -> Bool
altsAreExhaustive [Alt InVar]
alts)
= [Alt InVar] -> Maybe CpeRhs -> [Alt InVar]
forall b. [Alt b] -> Maybe (Expr b) -> [Alt b]
addDefault [Alt InVar]
alts (CpeRhs -> Maybe CpeRhs
forall a. a -> Maybe a
Just CpeRhs
err)
| Bool
otherwise = [Alt InVar]
alts
where err :: CpeRhs
err = Type -> String -> CpeRhs
mkImpossibleExpr Type
ty String
"cpeRhsE: missing case alternative"
; alts'' <- mapM (sat_alt env') alts'
; return (floats, Case scrut' bndr2 (cpSubstTy env ty) alts'') }
where
sat_alt :: CorePrepEnv -> Alt InVar -> UniqSM (Alt InVar)
sat_alt CorePrepEnv
env (Alt AltCon
con [InVar]
bs CpeRhs
rhs)
= do { (env2, bs') <- CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [InVar])
cpCloneBndrs CorePrepEnv
env [InVar]
bs
; rhs' <- cpeBodyNF env2 rhs
; return (Alt con bs' rhs') }
cpeBodyNF :: CorePrepEnv -> CoreExpr -> UniqSM CpeBody
cpeBodyNF :: CorePrepEnv -> CpeRhs -> UniqSM CpeRhs
cpeBodyNF CorePrepEnv
env CpeRhs
expr
= do { (floats, body) <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeBody CorePrepEnv
env CpeRhs
expr
; return (wrapBinds floats body) }
cpeBody :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeBody)
cpeBody :: CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeBody CorePrepEnv
env CpeRhs
expr
= do { (floats1, rhs) <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env CpeRhs
expr
; (floats2, body) <- rhsToBody rhs
; return (floats1 `appFloats` floats2, body) }
rhsToBody :: CpeRhs -> UniqSM (Floats, CpeBody)
rhsToBody :: CpeRhs -> UniqSM (Floats, CpeRhs)
rhsToBody (Tick CoreTickish
t CpeRhs
expr)
| CoreTickish -> TickishScoping
forall (pass :: TickishPass). GenTickish pass -> TickishScoping
tickishScoped CoreTickish
t TickishScoping -> TickishScoping -> Bool
forall a. Eq a => a -> a -> Bool
== TickishScoping
NoScope
= do { (floats, expr') <- CpeRhs -> UniqSM (Floats, CpeRhs)
rhsToBody CpeRhs
expr
; return (floats, mkTick t expr') }
rhsToBody (Cast CpeRhs
e Coercion
co)
= do { (floats, e') <- CpeRhs -> UniqSM (Floats, CpeRhs)
rhsToBody CpeRhs
e
; return (floats, Cast e' co) }
rhsToBody expr :: CpeRhs
expr@(Lam {})
| (InVar -> Bool) -> [InVar] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all InVar -> Bool
isTyVar [InVar]
bndrs
= (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
emptyFloats, CpeRhs
expr)
| Bool
otherwise
= do { let rhs :: CpeRhs
rhs = Int -> CpeRhs -> CpeRhs
cpeEtaExpand (CpeRhs -> Int
exprArity CpeRhs
expr) CpeRhs
expr
; fn <- Type -> UniqSM InVar
newVar (HasDebugCallStack => CpeRhs -> Type
CpeRhs -> Type
exprType CpeRhs
rhs)
; let float = CoreBind -> BindInfo -> FloatInfo -> FloatingBind
Float (InVar -> CpeRhs -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec InVar
fn CpeRhs
rhs) BindInfo
LetBound FloatInfo
TopLvlFloatable
; return (unitFloat float, Var fn) }
where
([InVar]
bndrs,CpeRhs
_) = CpeRhs -> ([InVar], CpeRhs)
forall b. Expr b -> ([b], Expr b)
collectBinders CpeRhs
expr
rhsToBody CpeRhs
expr = (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
emptyFloats, CpeRhs
expr)
data ArgInfo = CpeApp CoreArg
| CpeCast Coercion
| CpeTick CoreTickish
instance Outputable ArgInfo where
ppr :: ArgInfo -> SDoc
ppr (CpeApp CpeRhs
arg) = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"app" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CpeRhs -> SDoc
forall a. Outputable a => a -> SDoc
ppr CpeRhs
arg
ppr (CpeCast Coercion
co) = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"cast" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Coercion -> SDoc
forall a. Outputable a => a -> SDoc
ppr Coercion
co
ppr (CpeTick CoreTickish
tick) = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"tick" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CoreTickish -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreTickish
tick
cpeApp :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CpeRhs)
cpeApp :: CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeApp CorePrepEnv
top_env CpeRhs
expr
= do { let (CpeRhs
terminal, [ArgInfo]
args) = CpeRhs -> (CpeRhs, [ArgInfo])
collect_args CpeRhs
expr
; CorePrepEnv -> CpeRhs -> [ArgInfo] -> UniqSM (Floats, CpeRhs)
cpe_app CorePrepEnv
top_env CpeRhs
terminal [ArgInfo]
args
}
where
collect_args :: CoreExpr -> (CoreExpr, [ArgInfo])
collect_args :: CpeRhs -> (CpeRhs, [ArgInfo])
collect_args CpeRhs
e = CpeRhs -> [ArgInfo] -> (CpeRhs, [ArgInfo])
go CpeRhs
e []
where
go :: CpeRhs -> [ArgInfo] -> (CpeRhs, [ArgInfo])
go (App CpeRhs
fun CpeRhs
arg) [ArgInfo]
as
= CpeRhs -> [ArgInfo] -> (CpeRhs, [ArgInfo])
go CpeRhs
fun (CpeRhs -> ArgInfo
CpeApp CpeRhs
arg ArgInfo -> [ArgInfo] -> [ArgInfo]
forall a. a -> [a] -> [a]
: [ArgInfo]
as)
go (Cast CpeRhs
fun Coercion
co) [ArgInfo]
as
= CpeRhs -> [ArgInfo] -> (CpeRhs, [ArgInfo])
go CpeRhs
fun (Coercion -> ArgInfo
CpeCast Coercion
co ArgInfo -> [ArgInfo] -> [ArgInfo]
forall a. a -> [a] -> [a]
: [ArgInfo]
as)
go (Tick CoreTickish
tickish CpeRhs
fun) [ArgInfo]
as
| Var InVar
vh <- CpeRhs
head
, Var InVar
head' <- CorePrepEnv -> InVar -> CpeRhs
lookupCorePrepEnv CorePrepEnv
top_env InVar
vh
, InVar -> CoreTickish -> Bool
forall (pass :: TickishPass). InVar -> GenTickish pass -> Bool
etaExpansionTick InVar
head' CoreTickish
tickish
= (CpeRhs
head,[ArgInfo]
as')
where
(CpeRhs
head,[ArgInfo]
as') = CpeRhs -> [ArgInfo] -> (CpeRhs, [ArgInfo])
go CpeRhs
fun (CoreTickish -> ArgInfo
CpeTick CoreTickish
tickish ArgInfo -> [ArgInfo] -> [ArgInfo]
forall a. a -> [a] -> [a]
: [ArgInfo]
as)
go CpeRhs
terminal [ArgInfo]
as = (CpeRhs
terminal, [ArgInfo]
as)
cpe_app :: CorePrepEnv
-> CoreExpr
-> [ArgInfo]
-> UniqSM (Floats, CpeRhs)
cpe_app :: CorePrepEnv -> CpeRhs -> [ArgInfo] -> UniqSM (Floats, CpeRhs)
cpe_app CorePrepEnv
env (Var InVar
f) (CpeApp Type{} : CpeApp CpeRhs
arg : [ArgInfo]
args)
| InVar
f InVar -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
lazyIdKey
Bool -> Bool -> Bool
|| InVar
f InVar -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
noinlineIdKey Bool -> Bool -> Bool
|| InVar
f InVar -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
noinlineConstraintIdKey
Bool -> Bool -> Bool
|| InVar
f InVar -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
nospecIdKey
= let (CpeRhs
terminal, [ArgInfo]
args') = CpeRhs -> (CpeRhs, [ArgInfo])
collect_args CpeRhs
arg
in CorePrepEnv -> CpeRhs -> [ArgInfo] -> UniqSM (Floats, CpeRhs)
cpe_app CorePrepEnv
env CpeRhs
terminal ([ArgInfo]
args' [ArgInfo] -> [ArgInfo] -> [ArgInfo]
forall a. [a] -> [a] -> [a]
++ [ArgInfo]
args)
cpe_app CorePrepEnv
env (Var InVar
f) (CpeApp _runtimeRep :: CpeRhs
_runtimeRep@Type{} : CpeApp _type :: CpeRhs
_type@Type{} : CpeApp CpeRhs
arg : [ArgInfo]
rest)
| InVar
f InVar -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
runRWKey
, [ArgInfo] -> Bool
has_value_arg (CpeRhs -> ArgInfo
CpeApp CpeRhs
arg ArgInfo -> [ArgInfo] -> [ArgInfo]
forall a. a -> [a] -> [a]
: [ArgInfo]
rest)
= case CpeRhs
arg of
Lam InVar
s CpeRhs
body -> CorePrepEnv -> CpeRhs -> [ArgInfo] -> UniqSM (Floats, CpeRhs)
cpe_app (CorePrepEnv -> InVar -> InVar -> CorePrepEnv
extendCorePrepEnv CorePrepEnv
env InVar
s InVar
realWorldPrimId) CpeRhs
body [ArgInfo]
rest
CpeRhs
_ -> CorePrepEnv -> CpeRhs -> [ArgInfo] -> UniqSM (Floats, CpeRhs)
cpe_app CorePrepEnv
env CpeRhs
arg (CpeRhs -> ArgInfo
CpeApp (InVar -> CpeRhs
forall b. InVar -> Expr b
Var InVar
realWorldPrimId) ArgInfo -> [ArgInfo] -> [ArgInfo]
forall a. a -> [a] -> [a]
: [ArgInfo]
rest)
where
has_value_arg :: [ArgInfo] -> Bool
has_value_arg [] = Bool
False
has_value_arg (CpeApp CpeRhs
arg:[ArgInfo]
_rest)
| Bool -> Bool
not (CpeRhs -> Bool
forall b. Expr b -> Bool
isTyCoArg CpeRhs
arg) = Bool
True
has_value_arg (ArgInfo
_:[ArgInfo]
rest) = [ArgInfo] -> Bool
has_value_arg [ArgInfo]
rest
cpe_app CorePrepEnv
env (Var InVar
v) [ArgInfo]
args
= do { v1 <- InVar -> UniqSM InVar
fiddleCCall InVar
v
; let e2 = CorePrepEnv -> InVar -> CpeRhs
lookupCorePrepEnv CorePrepEnv
env InVar
v1
hd = CpeRhs -> Maybe InVar
getIdFromTrivialExpr_maybe CpeRhs
e2
min_arity = case Maybe InVar
hd of
Just InVar
v_hd -> if InVar -> Bool
hasNoBinding InVar
v_hd then Int -> Maybe Int
forall a. a -> Maybe a
Just (Int -> Maybe Int) -> Int -> Maybe Int
forall a b. (a -> b) -> a -> b
$! (InVar -> Int
idArity InVar
v_hd) else Maybe Int
forall a. Maybe a
Nothing
Maybe InVar
Nothing -> Maybe Int
forall a. Maybe a
Nothing
; (app, floats, unsat_ticks) <- rebuild_app env args e2 emptyFloats stricts min_arity
; mb_saturate hd app floats unsat_ticks depth }
where
depth :: Int
depth = [ArgInfo] -> Int
val_args [ArgInfo]
args
stricts :: [Demand]
stricts = case InVar -> DmdSig
idDmdSig InVar
v of
DmdSig (DmdType DmdEnv
_ [Demand]
demands)
| [Demand] -> Int -> Ordering
forall a. [a] -> Int -> Ordering
listLengthCmp [Demand]
demands Int
depth Ordering -> Ordering -> Bool
forall a. Eq a => a -> a -> Bool
/= Ordering
GT -> [Demand]
demands
| Bool
otherwise -> []
cpe_app CorePrepEnv
env CpeRhs
fun [] = CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env CpeRhs
fun
cpe_app CorePrepEnv
env CpeRhs
fun [ArgInfo]
args
= do { (fun_floats, fun') <- CorePrepEnv -> Demand -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeArg CorePrepEnv
env Demand
evalDmd CpeRhs
fun
; (app, floats,unsat_ticks) <- rebuild_app env args fun' fun_floats [] Nothing
; mb_saturate Nothing app floats unsat_ticks (val_args args) }
val_args :: [ArgInfo] -> Int
val_args :: [ArgInfo] -> Int
val_args [ArgInfo]
args = [ArgInfo] -> Int -> Int
forall {t}. Num t => [ArgInfo] -> t -> t
go [ArgInfo]
args Int
0
where
go :: [ArgInfo] -> t -> t
go [] !t
n = t
n
go (ArgInfo
info:[ArgInfo]
infos) t
n =
case ArgInfo
info of
CpeCast {} -> [ArgInfo] -> t -> t
go [ArgInfo]
infos t
n
CpeTick CoreTickish
tickish
| CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
tickishFloatable CoreTickish
tickish -> [ArgInfo] -> t -> t
go [ArgInfo]
infos t
n
| Bool
otherwise -> t
n
CpeApp CpeRhs
e -> [ArgInfo] -> t -> t
go [ArgInfo]
infos t
n'
where
!n' :: t
n'
| CpeRhs -> Bool
forall b. Expr b -> Bool
isTypeArg CpeRhs
e = t
n
| Bool
otherwise = t
nt -> t -> t
forall a. Num a => a -> a -> a
+t
1
mb_saturate :: Maybe InVar
-> CpeRhs -> a -> [CoreTickish] -> Int -> UniqSM (a, CpeRhs)
mb_saturate Maybe InVar
head CpeRhs
app a
floats [CoreTickish]
unsat_ticks Int
depth =
case Maybe InVar
head of
Just InVar
fn_id -> do { sat_app <- InVar -> CpeRhs -> Int -> [CoreTickish] -> UniqSM CpeRhs
maybeSaturate InVar
fn_id CpeRhs
app Int
depth [CoreTickish]
unsat_ticks
; return (floats, sat_app) }
Maybe InVar
_other -> do { Bool -> UniqSM ()
forall (m :: * -> *). (HasCallStack, Applicative m) => Bool -> m ()
massert ([CoreTickish] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreTickish]
unsat_ticks)
; (a, CpeRhs) -> UniqSM (a, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (a
floats, CpeRhs
app) }
rebuild_app
:: CorePrepEnv
-> [ArgInfo]
-> CpeApp
-> Floats
-> [Demand]
-> Maybe Arity
-> UniqSM (CpeApp
,Floats
,[CoreTickish]
)
rebuild_app :: CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> Maybe Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app CorePrepEnv
env [ArgInfo]
args CpeRhs
app Floats
floats [Demand]
ss Maybe Int
req_depth =
CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
env [ArgInfo]
args CpeRhs
app Floats
floats [Demand]
ss [] (Int -> Maybe Int -> Int
forall a. a -> Maybe a -> a
fromMaybe Int
0 Maybe Int
req_depth)
rebuild_app'
:: CorePrepEnv
-> [ArgInfo]
-> CpeApp
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeApp, Floats, [CoreTickish])
rebuild_app' :: CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
_ [] CpeRhs
app Floats
floats [Demand]
ss [CoreTickish]
rt_ticks !Int
_req_depth
= Bool
-> SDoc
-> ((CpeRhs, Floats, [CoreTickish])
-> UniqSM (CpeRhs, Floats, [CoreTickish]))
-> (CpeRhs, Floats, [CoreTickish])
-> UniqSM (CpeRhs, Floats, [CoreTickish])
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr ([Demand] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Demand]
ss) ([Demand] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Demand]
ss)
(CpeRhs, Floats, [CoreTickish])
-> UniqSM (CpeRhs, Floats, [CoreTickish])
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (CpeRhs
app, Floats
floats, [CoreTickish]
rt_ticks)
rebuild_app' CorePrepEnv
env (ArgInfo
a : [ArgInfo]
as) CpeRhs
fun' Floats
floats [Demand]
ss [CoreTickish]
rt_ticks Int
req_depth = case ArgInfo
a of
ArgInfo
_
| Bool -> Bool
not ([CoreTickish] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreTickish]
rt_ticks)
, Int
req_depth Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
<= Int
0
->
let tick_fun :: CpeRhs
tick_fun = (CoreTickish -> CpeRhs -> CpeRhs)
-> CpeRhs -> [CoreTickish] -> CpeRhs
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr CoreTickish -> CpeRhs -> CpeRhs
mkTick CpeRhs
fun' [CoreTickish]
rt_ticks
in CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
env (ArgInfo
a ArgInfo -> [ArgInfo] -> [ArgInfo]
forall a. a -> [a] -> [a]
: [ArgInfo]
as) CpeRhs
tick_fun Floats
floats [Demand]
ss [CoreTickish]
rt_ticks Int
req_depth
CpeApp (Type Type
arg_ty)
-> CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
env [ArgInfo]
as (CpeRhs -> CpeRhs -> CpeRhs
forall b. Expr b -> Expr b -> Expr b
App CpeRhs
fun' (Type -> CpeRhs
forall b. Type -> Expr b
Type Type
arg_ty')) Floats
floats [Demand]
ss [CoreTickish]
rt_ticks Int
req_depth
where
arg_ty' :: Type
arg_ty' = CorePrepEnv -> Type -> Type
cpSubstTy CorePrepEnv
env Type
arg_ty
CpeApp (Coercion Coercion
co)
-> CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
env [ArgInfo]
as (CpeRhs -> CpeRhs -> CpeRhs
forall b. Expr b -> Expr b -> Expr b
App CpeRhs
fun' (Coercion -> CpeRhs
forall b. Coercion -> Expr b
Coercion Coercion
co')) Floats
floats (Int -> [Demand] -> [Demand]
forall a. Int -> [a] -> [a]
drop Int
1 [Demand]
ss) [CoreTickish]
rt_ticks Int
req_depth
where
co' :: Coercion
co' = CorePrepEnv -> Coercion -> Coercion
cpSubstCo CorePrepEnv
env Coercion
co
CpeApp CpeRhs
arg -> do
let (Demand
ss1, [Demand]
ss_rest)
= case ([Demand]
ss, CpeRhs -> Bool
isLazyExpr CpeRhs
arg) of
(Demand
_ : [Demand]
ss_rest, Bool
True) -> (Demand
topDmd, [Demand]
ss_rest)
(Demand
ss1 : [Demand]
ss_rest, Bool
False) -> (Demand
ss1, [Demand]
ss_rest)
([], Bool
_) -> (Demand
topDmd, [])
(fs, arg') <- CorePrepEnv -> Demand -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeArg CorePrepEnv
top_env Demand
ss1 CpeRhs
arg
rebuild_app' env as (App fun' arg') (fs `zipFloats` floats) ss_rest rt_ticks (req_depth-1)
CpeCast Coercion
co
-> CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
env [ArgInfo]
as (CpeRhs -> Coercion -> CpeRhs
forall b. Expr b -> Coercion -> Expr b
Cast CpeRhs
fun' Coercion
co') Floats
floats [Demand]
ss [CoreTickish]
rt_ticks Int
req_depth
where
co' :: Coercion
co' = CorePrepEnv -> Coercion -> Coercion
cpSubstCo CorePrepEnv
env Coercion
co
CpeTick CoreTickish
tickish
| CoreTickish -> TickishPlacement
forall (pass :: TickishPass). GenTickish pass -> TickishPlacement
tickishPlace CoreTickish
tickish TickishPlacement -> TickishPlacement -> Bool
forall a. Eq a => a -> a -> Bool
== TickishPlacement
PlaceRuntime
, Int
req_depth Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
-> Bool
-> UniqSM (CpeRhs, Floats, [CoreTickish])
-> UniqSM (CpeRhs, Floats, [CoreTickish])
forall a. HasCallStack => Bool -> a -> a
assert (CoreTickish -> Bool
forall (pass :: TickishPass). GenTickish pass -> Bool
isProfTick CoreTickish
tickish) (UniqSM (CpeRhs, Floats, [CoreTickish])
-> UniqSM (CpeRhs, Floats, [CoreTickish]))
-> UniqSM (CpeRhs, Floats, [CoreTickish])
-> UniqSM (CpeRhs, Floats, [CoreTickish])
forall a b. (a -> b) -> a -> b
$
CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
env [ArgInfo]
as CpeRhs
fun' Floats
floats [Demand]
ss (CoreTickish
tickishCoreTickish -> [CoreTickish] -> [CoreTickish]
forall a. a -> [a] -> [a]
:[CoreTickish]
rt_ticks) Int
req_depth
| Bool
otherwise
-> CorePrepEnv
-> [ArgInfo]
-> CpeRhs
-> Floats
-> [Demand]
-> [CoreTickish]
-> Int
-> UniqSM (CpeRhs, Floats, [CoreTickish])
rebuild_app' CorePrepEnv
env [ArgInfo]
as CpeRhs
fun' (Floats -> FloatingBind -> Floats
snocFloat Floats
floats (CoreTickish -> FloatingBind
FloatTick CoreTickish
tickish)) [Demand]
ss [CoreTickish]
rt_ticks Int
req_depth
isLazyExpr :: CoreExpr -> Bool
isLazyExpr :: CpeRhs -> Bool
isLazyExpr (Cast CpeRhs
e Coercion
_) = CpeRhs -> Bool
isLazyExpr CpeRhs
e
isLazyExpr (Tick CoreTickish
_ CpeRhs
e) = CpeRhs -> Bool
isLazyExpr CpeRhs
e
isLazyExpr (Var InVar
f `App` CpeRhs
_ `App` CpeRhs
_) = InVar
f InVar -> Unique -> Bool
forall a. Uniquable a => a -> Unique -> Bool
`hasKey` Unique
lazyIdKey
isLazyExpr CpeRhs
_ = Bool
False
cpeArg :: CorePrepEnv -> Demand
-> CoreArg -> UniqSM (Floats, CpeArg)
cpeArg :: CorePrepEnv -> Demand -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeArg CorePrepEnv
env Demand
dmd CpeRhs
arg
= do { (floats1, arg1) <- CorePrepEnv -> CpeRhs -> UniqSM (Floats, CpeRhs)
cpeRhsE CorePrepEnv
env CpeRhs
arg
; let arg_ty = HasDebugCallStack => CpeRhs -> Type
CpeRhs -> Type
exprType CpeRhs
arg1
is_unlifted = HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType Type
arg_ty
dec = RecFlag -> Demand -> Bool -> Floats -> CpeRhs -> FloatDecision
wantFloatLocal RecFlag
NonRecursive Demand
dmd Bool
is_unlifted Floats
floats1 CpeRhs
arg1
; (floats2, arg2) <- executeFloatDecision dec floats1 arg1
; if exprIsTrivial arg2
then return (floats2, arg2)
else do { v <- newVar arg_ty
; let arity = CorePrepEnv -> FloatDecision -> CpeRhs -> Int
cpeArgArity CorePrepEnv
env FloatDecision
dec CpeRhs
arg2
arg3 = Int -> CpeRhs -> CpeRhs
cpeEtaExpand Int
arity CpeRhs
arg2
arg_float = CorePrepEnv -> Demand -> Bool -> InVar -> CpeRhs -> FloatingBind
mkNonRecFloat CorePrepEnv
env Demand
dmd Bool
is_unlifted InVar
v CpeRhs
arg3
; return (snocFloat floats2 arg_float, varToCoreExpr v) }
}
cpeArgArity :: CorePrepEnv -> FloatDecision -> CoreArg -> Arity
cpeArgArity :: CorePrepEnv -> FloatDecision -> CpeRhs -> Int
cpeArgArity CorePrepEnv
env FloatDecision
float_decision CpeRhs
arg
| FloatDecision
FloatNone <- FloatDecision
float_decision
= Int
0
| Just ArityOpts
ao <- CorePrepConfig -> Maybe ArityOpts
cp_arityOpts (CorePrepEnv -> CorePrepConfig
cpe_config CorePrepEnv
env)
, Bool -> Bool
not (CpeRhs -> Bool
has_join_in_tail_context CpeRhs
arg)
= case ArityOpts -> CpeRhs -> Maybe SafeArityType
exprEtaExpandArity ArityOpts
ao CpeRhs
arg of
Maybe SafeArityType
Nothing -> Int
0
Just SafeArityType
at -> SafeArityType -> Int
arityTypeArity SafeArityType
at
| Bool
otherwise
= CpeRhs -> Int
exprArity CpeRhs
arg
has_join_in_tail_context :: CoreExpr -> Bool
has_join_in_tail_context :: CpeRhs -> Bool
has_join_in_tail_context (Let CoreBind
bs CpeRhs
e) = CoreBind -> Bool
isJoinBind CoreBind
bs Bool -> Bool -> Bool
|| CpeRhs -> Bool
has_join_in_tail_context CpeRhs
e
has_join_in_tail_context (Lam InVar
b CpeRhs
e) | InVar -> Bool
isTyVar InVar
b = CpeRhs -> Bool
has_join_in_tail_context CpeRhs
e
has_join_in_tail_context (Cast CpeRhs
e Coercion
_) = CpeRhs -> Bool
has_join_in_tail_context CpeRhs
e
has_join_in_tail_context (Tick CoreTickish
_ CpeRhs
e) = CpeRhs -> Bool
has_join_in_tail_context CpeRhs
e
has_join_in_tail_context (Case CpeRhs
_ InVar
_ Type
_ [Alt InVar]
alts) = (CpeRhs -> Bool) -> [CpeRhs] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any CpeRhs -> Bool
has_join_in_tail_context ([Alt InVar] -> [CpeRhs]
forall b. [Alt b] -> [Expr b]
rhssOfAlts [Alt InVar]
alts)
has_join_in_tail_context CpeRhs
_ = Bool
False
maybeSaturate :: Id -> CpeApp -> Int -> [CoreTickish] -> UniqSM CpeRhs
maybeSaturate :: InVar -> CpeRhs -> Int -> [CoreTickish] -> UniqSM CpeRhs
maybeSaturate InVar
fn CpeRhs
expr Int
n_args [CoreTickish]
unsat_ticks
| InVar -> Bool
hasNoBinding InVar
fn
= CpeRhs -> UniqSM CpeRhs
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (CpeRhs -> UniqSM CpeRhs) -> CpeRhs -> UniqSM CpeRhs
forall a b. (a -> b) -> a -> b
$ (CpeRhs -> CpeRhs) -> CpeRhs -> CpeRhs
wrapLamBody (\CpeRhs
body -> (CoreTickish -> CpeRhs -> CpeRhs)
-> CpeRhs -> [CoreTickish] -> CpeRhs
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr CoreTickish -> CpeRhs -> CpeRhs
mkTick CpeRhs
body [CoreTickish]
unsat_ticks) CpeRhs
sat_expr
| Int
mark_arity Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
> Int
0
, Bool -> Bool
not Bool
applied_marks
= Bool -> SDoc -> UniqSM CpeRhs -> UniqSM CpeRhs
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr
( Bool -> Bool
not (InVar -> Bool
isJoinId InVar
fn))
( InVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr InVar
fn SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"expr:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CpeRhs -> SDoc
forall a. Outputable a => a -> SDoc
ppr CpeRhs
expr SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$ String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"n_args:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
n_args SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"marks:" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Maybe [CbvMark] -> SDoc
forall a. Outputable a => a -> SDoc
ppr (InVar -> Maybe [CbvMark]
idCbvMarks_maybe InVar
fn) SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"join_arity" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> JoinPointHood -> SDoc
forall a. Outputable a => a -> SDoc
ppr (InVar -> JoinPointHood
idJoinPointHood InVar
fn) SDoc -> SDoc -> SDoc
forall doc. IsDoc doc => doc -> doc -> doc
$$
String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"fn_arity" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
fn_arity
) (UniqSM CpeRhs -> UniqSM CpeRhs) -> UniqSM CpeRhs -> UniqSM CpeRhs
forall a b. (a -> b) -> a -> b
$
CpeRhs -> UniqSM CpeRhs
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return CpeRhs
sat_expr
| Bool
otherwise
= Bool -> UniqSM CpeRhs -> UniqSM CpeRhs
forall a. HasCallStack => Bool -> a -> a
assert ([CoreTickish] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CoreTickish]
unsat_ticks) (UniqSM CpeRhs -> UniqSM CpeRhs) -> UniqSM CpeRhs -> UniqSM CpeRhs
forall a b. (a -> b) -> a -> b
$
CpeRhs -> UniqSM CpeRhs
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return CpeRhs
expr
where
mark_arity :: Int
mark_arity = InVar -> Int
idCbvMarkArity InVar
fn
fn_arity :: Int
fn_arity = InVar -> Int
idArity InVar
fn
excess_arity :: Int
excess_arity = (Int -> Int -> Int
forall a. Ord a => a -> a -> a
max Int
fn_arity Int
mark_arity) Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n_args
sat_expr :: CpeRhs
sat_expr = Int -> CpeRhs -> CpeRhs
cpeEtaExpand Int
excess_arity CpeRhs
expr
applied_marks :: Bool
applied_marks = Int
n_args Int -> Int -> Bool
forall a. Ord a => a -> a -> Bool
>= ([CbvMark] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ([CbvMark] -> Int)
-> (Maybe [CbvMark] -> [CbvMark]) -> Maybe [CbvMark] -> Int
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (CbvMark -> Bool) -> [CbvMark] -> [CbvMark]
forall a. (a -> Bool) -> [a] -> [a]
dropWhile (Bool -> Bool
not (Bool -> Bool) -> (CbvMark -> Bool) -> CbvMark -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CbvMark -> Bool
isMarkedCbv) ([CbvMark] -> [CbvMark])
-> (Maybe [CbvMark] -> [CbvMark]) -> Maybe [CbvMark] -> [CbvMark]
forall b c a. (b -> c) -> (a -> b) -> a -> c
.
[CbvMark] -> [CbvMark]
forall a. [a] -> [a]
reverse ([CbvMark] -> [CbvMark])
-> (Maybe [CbvMark] -> [CbvMark]) -> Maybe [CbvMark] -> [CbvMark]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Maybe [CbvMark] -> [CbvMark]
forall a. HasCallStack => String -> Maybe a -> a
expectJust String
"maybeSaturate" (Maybe [CbvMark] -> Int) -> Maybe [CbvMark] -> Int
forall a b. (a -> b) -> a -> b
$ (InVar -> Maybe [CbvMark]
idCbvMarks_maybe InVar
fn))
cpeEtaExpand :: Arity -> CpeRhs -> CpeRhs
cpeEtaExpand :: Int -> CpeRhs -> CpeRhs
cpeEtaExpand Int
arity CpeRhs
expr
| Int
arity Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== Int
0 = CpeRhs
expr
| Bool
otherwise = Int -> CpeRhs -> CpeRhs
etaExpand Int
arity CpeRhs
expr
data BindInfo
= CaseBound
| LetBound
deriving BindInfo -> BindInfo -> Bool
(BindInfo -> BindInfo -> Bool)
-> (BindInfo -> BindInfo -> Bool) -> Eq BindInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: BindInfo -> BindInfo -> Bool
== :: BindInfo -> BindInfo -> Bool
$c/= :: BindInfo -> BindInfo -> Bool
/= :: BindInfo -> BindInfo -> Bool
Eq
data FloatInfo
= TopLvlFloatable
| LazyContextFloatable
| StrictContextFloatable
deriving FloatInfo -> FloatInfo -> Bool
(FloatInfo -> FloatInfo -> Bool)
-> (FloatInfo -> FloatInfo -> Bool) -> Eq FloatInfo
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: FloatInfo -> FloatInfo -> Bool
== :: FloatInfo -> FloatInfo -> Bool
$c/= :: FloatInfo -> FloatInfo -> Bool
/= :: FloatInfo -> FloatInfo -> Bool
Eq
instance Outputable BindInfo where
ppr :: BindInfo -> SDoc
ppr BindInfo
CaseBound = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Case"
ppr BindInfo
LetBound = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Let"
instance Outputable FloatInfo where
ppr :: FloatInfo -> SDoc
ppr FloatInfo
TopLvlFloatable = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"top-lvl"
ppr FloatInfo
LazyContextFloatable = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"lzy-ctx"
ppr FloatInfo
StrictContextFloatable = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"str-ctx"
data FloatingBind
= Float !CoreBind !BindInfo !FloatInfo
| UnsafeEqualityCase !CoreExpr !CoreBndr !AltCon ![CoreBndr]
| FloatTick CoreTickish
data Floats
= Floats
{ Floats -> FloatInfo
fs_info :: !FloatInfo
, Floats -> OrdList FloatingBind
fs_binds :: !(OrdList FloatingBind)
}
instance Outputable FloatingBind where
ppr :: FloatingBind -> SDoc
ppr (Float CoreBind
b BindInfo
bi FloatInfo
fi) = BindInfo -> SDoc
forall a. Outputable a => a -> SDoc
ppr BindInfo
bi SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> FloatInfo -> SDoc
forall a. Outputable a => a -> SDoc
ppr FloatInfo
fi SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CoreBind -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreBind
b
ppr (FloatTick CoreTickish
t) = CoreTickish -> SDoc
forall a. Outputable a => a -> SDoc
ppr CoreTickish
t
ppr (UnsafeEqualityCase CpeRhs
scrut InVar
b AltCon
k [InVar]
bs) = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"case" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> CpeRhs -> SDoc
forall a. Outputable a => a -> SDoc
ppr CpeRhs
scrut
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"of"SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> InVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr InVar
b SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"@"
SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> case [InVar]
bs of
[] -> AltCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr AltCon
k
[InVar]
_ -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
parens (AltCon -> SDoc
forall a. Outputable a => a -> SDoc
ppr AltCon
k SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<+> [InVar] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [InVar]
bs)
instance Outputable Floats where
ppr :: Floats -> SDoc
ppr (Floats FloatInfo
info OrdList FloatingBind
binds) = String -> SDoc
forall doc. IsLine doc => String -> doc
text String
"Floats" SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
brackets (FloatInfo -> SDoc
forall a. Outputable a => a -> SDoc
ppr FloatInfo
info) SDoc -> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc -> doc
<> SDoc -> SDoc
forall doc. IsLine doc => doc -> doc
braces (OrdList FloatingBind -> SDoc
forall a. Outputable a => a -> SDoc
ppr OrdList FloatingBind
binds)
lubFloatInfo :: FloatInfo -> FloatInfo -> FloatInfo
lubFloatInfo :: FloatInfo -> FloatInfo -> FloatInfo
lubFloatInfo FloatInfo
StrictContextFloatable FloatInfo
_ = FloatInfo
StrictContextFloatable
lubFloatInfo FloatInfo
_ FloatInfo
StrictContextFloatable = FloatInfo
StrictContextFloatable
lubFloatInfo FloatInfo
LazyContextFloatable FloatInfo
_ = FloatInfo
LazyContextFloatable
lubFloatInfo FloatInfo
_ FloatInfo
LazyContextFloatable = FloatInfo
LazyContextFloatable
lubFloatInfo FloatInfo
TopLvlFloatable FloatInfo
TopLvlFloatable = FloatInfo
TopLvlFloatable
floatsAtLeastAsFarAs :: FloatInfo -> FloatInfo -> Bool
floatsAtLeastAsFarAs :: FloatInfo -> FloatInfo -> Bool
floatsAtLeastAsFarAs FloatInfo
l FloatInfo
r = FloatInfo
l FloatInfo -> FloatInfo -> FloatInfo
`lubFloatInfo` FloatInfo
r FloatInfo -> FloatInfo -> Bool
forall a. Eq a => a -> a -> Bool
== FloatInfo
r
emptyFloats :: Floats
emptyFloats :: Floats
emptyFloats = FloatInfo -> OrdList FloatingBind -> Floats
Floats FloatInfo
TopLvlFloatable OrdList FloatingBind
forall a. OrdList a
nilOL
isEmptyFloats :: Floats -> Bool
isEmptyFloats :: Floats -> Bool
isEmptyFloats (Floats FloatInfo
_ OrdList FloatingBind
b) = OrdList FloatingBind -> Bool
forall a. OrdList a -> Bool
isNilOL OrdList FloatingBind
b
getFloats :: Floats -> OrdList FloatingBind
getFloats :: Floats -> OrdList FloatingBind
getFloats = Floats -> OrdList FloatingBind
fs_binds
unitFloat :: FloatingBind -> Floats
unitFloat :: FloatingBind -> Floats
unitFloat = Floats -> FloatingBind -> Floats
snocFloat Floats
emptyFloats
floatInfo :: FloatingBind -> FloatInfo
floatInfo :: FloatingBind -> FloatInfo
floatInfo (Float CoreBind
_ BindInfo
_ FloatInfo
info) = FloatInfo
info
floatInfo UnsafeEqualityCase{} = FloatInfo
LazyContextFloatable
floatInfo FloatTick{} = FloatInfo
TopLvlFloatable
snocFloat :: Floats -> FloatingBind -> Floats
snocFloat :: Floats -> FloatingBind -> Floats
snocFloat Floats
floats FloatingBind
fb =
Floats { fs_info :: FloatInfo
fs_info = FloatInfo -> FloatInfo -> FloatInfo
lubFloatInfo (Floats -> FloatInfo
fs_info Floats
floats) (FloatingBind -> FloatInfo
floatInfo FloatingBind
fb)
, fs_binds :: OrdList FloatingBind
fs_binds = Floats -> OrdList FloatingBind
fs_binds Floats
floats OrdList FloatingBind -> FloatingBind -> OrdList FloatingBind
forall a. OrdList a -> a -> OrdList a
`snocOL` FloatingBind
fb }
consFloat :: FloatingBind -> Floats -> Floats
consFloat :: FloatingBind -> Floats -> Floats
consFloat FloatingBind
fb Floats
floats =
Floats { fs_info :: FloatInfo
fs_info = FloatInfo -> FloatInfo -> FloatInfo
lubFloatInfo (Floats -> FloatInfo
fs_info Floats
floats) (FloatingBind -> FloatInfo
floatInfo FloatingBind
fb)
, fs_binds :: OrdList FloatingBind
fs_binds = FloatingBind
fb FloatingBind -> OrdList FloatingBind -> OrdList FloatingBind
forall a. a -> OrdList a -> OrdList a
`consOL` Floats -> OrdList FloatingBind
fs_binds Floats
floats }
appFloats :: Floats -> Floats -> Floats
appFloats :: Floats -> Floats -> Floats
appFloats Floats
outer Floats
inner =
Floats { fs_info :: FloatInfo
fs_info = FloatInfo -> FloatInfo -> FloatInfo
lubFloatInfo (Floats -> FloatInfo
fs_info Floats
outer) (Floats -> FloatInfo
fs_info Floats
inner)
, fs_binds :: OrdList FloatingBind
fs_binds = Floats -> OrdList FloatingBind
fs_binds Floats
outer OrdList FloatingBind
-> OrdList FloatingBind -> OrdList FloatingBind
forall a. OrdList a -> OrdList a -> OrdList a
`appOL` Floats -> OrdList FloatingBind
fs_binds Floats
inner }
zipFloats :: Floats -> Floats -> Floats
zipFloats :: Floats -> Floats -> Floats
zipFloats = Floats -> Floats -> Floats
appFloats
zipManyFloats :: [Floats] -> Floats
zipManyFloats :: [Floats] -> Floats
zipManyFloats = (Floats -> Floats -> Floats) -> Floats -> [Floats] -> Floats
forall a b. (a -> b -> b) -> b -> [a] -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Floats -> Floats -> Floats
zipFloats Floats
emptyFloats
mkNonRecFloat :: CorePrepEnv -> Demand -> Bool -> Id -> CpeRhs -> FloatingBind
mkNonRecFloat :: CorePrepEnv -> Demand -> Bool -> InVar -> CpeRhs -> FloatingBind
mkNonRecFloat CorePrepEnv
env Demand
dmd Bool
is_unlifted InVar
bndr CpeRhs
rhs
=
CoreBind -> BindInfo -> FloatInfo -> FloatingBind
Float (InVar -> CpeRhs -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec InVar
bndr' CpeRhs
rhs) BindInfo
bound FloatInfo
info
where
bndr' :: InVar
bndr' = InVar -> Demand -> InVar
setIdDemandInfo InVar
bndr Demand
dmd
(BindInfo
bound,FloatInfo
info)
| Bool
is_lifted, Bool
is_hnf = (BindInfo
LetBound, FloatInfo
TopLvlFloatable)
| InVar -> Bool
is_data_con InVar
bndr = (BindInfo
LetBound, FloatInfo
TopLvlFloatable)
| CpeRhs -> Bool
exprIsTickedString CpeRhs
rhs = (BindInfo
CaseBound, FloatInfo
TopLvlFloatable)
| Bool
is_unlifted, Bool
ok_for_spec = (BindInfo
CaseBound, FloatInfo
LazyContextFloatable)
| Bool
is_lifted, Bool
ok_for_spec = (BindInfo
CaseBound, FloatInfo
TopLvlFloatable)
| Bool
is_unlifted Bool -> Bool -> Bool
|| Bool
is_strict = (BindInfo
CaseBound, FloatInfo
StrictContextFloatable)
| Bool
otherwise = Bool -> SDoc -> (BindInfo, FloatInfo) -> (BindInfo, FloatInfo)
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr Bool
is_lifted (CpeRhs -> SDoc
forall a. Outputable a => a -> SDoc
ppr CpeRhs
rhs) ((BindInfo, FloatInfo) -> (BindInfo, FloatInfo))
-> (BindInfo, FloatInfo) -> (BindInfo, FloatInfo)
forall a b. (a -> b) -> a -> b
$
(BindInfo
LetBound, FloatInfo
TopLvlFloatable)
is_lifted :: Bool
is_lifted = Bool -> Bool
not Bool
is_unlifted
is_hnf :: Bool
is_hnf = CpeRhs -> Bool
exprIsHNF CpeRhs
rhs
is_strict :: Bool
is_strict = Demand -> Bool
isStrUsedDmd Demand
dmd
ok_for_spec :: Bool
ok_for_spec = (InVar -> Bool) -> CpeRhs -> Bool
exprOkForSpecEval (Bool -> Bool
not (Bool -> Bool) -> (InVar -> Bool) -> InVar -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InVar -> Bool
is_rec_call) CpeRhs
rhs
is_rec_call :: InVar -> Bool
is_rec_call = (InVar -> UnVarSet -> Bool
`elemUnVarSet` CorePrepEnv -> UnVarSet
cpe_rec_ids CorePrepEnv
env)
is_data_con :: InVar -> Bool
is_data_con = Maybe DataCon -> Bool
forall a. Maybe a -> Bool
isJust (Maybe DataCon -> Bool)
-> (InVar -> Maybe DataCon) -> InVar -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. InVar -> Maybe DataCon
isDataConId_maybe
wrapBinds :: Floats -> CpeBody -> CpeBody
wrapBinds :: Floats -> CpeRhs -> CpeRhs
wrapBinds Floats
floats CpeRhs
body
=
(FloatingBind -> CpeRhs -> CpeRhs)
-> CpeRhs -> OrdList FloatingBind -> CpeRhs
forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL FloatingBind -> CpeRhs -> CpeRhs
mk_bind CpeRhs
body (Floats -> OrdList FloatingBind
getFloats Floats
floats)
where
mk_bind :: FloatingBind -> CpeRhs -> CpeRhs
mk_bind f :: FloatingBind
f@(Float CoreBind
bind BindInfo
CaseBound FloatInfo
_) CpeRhs
body
| NonRec InVar
bndr CpeRhs
rhs <- CoreBind
bind
= CpeRhs -> InVar -> CpeRhs -> CpeRhs
mkDefaultCase CpeRhs
rhs InVar
bndr CpeRhs
body
| Bool
otherwise
= String -> SDoc -> CpeRhs
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"wrapBinds" (FloatingBind -> SDoc
forall a. Outputable a => a -> SDoc
ppr FloatingBind
f)
mk_bind (Float CoreBind
bind BindInfo
_ FloatInfo
_) CpeRhs
body
= CoreBind -> CpeRhs -> CpeRhs
forall b. Bind b -> Expr b -> Expr b
Let CoreBind
bind CpeRhs
body
mk_bind (UnsafeEqualityCase CpeRhs
scrut InVar
b AltCon
con [InVar]
bs) CpeRhs
body
= CpeRhs -> InVar -> AltCon -> [InVar] -> CpeRhs -> CpeRhs
mkSingleAltCase CpeRhs
scrut InVar
b AltCon
con [InVar]
bs CpeRhs
body
mk_bind (FloatTick CoreTickish
tickish) CpeRhs
body
= CoreTickish -> CpeRhs -> CpeRhs
mkTick CoreTickish
tickish CpeRhs
body
deFloatTop :: Floats -> [CoreBind]
deFloatTop :: Floats -> CoreProgram
deFloatTop Floats
floats
= (FloatingBind -> CoreProgram -> CoreProgram)
-> CoreProgram -> OrdList FloatingBind -> CoreProgram
forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL FloatingBind -> CoreProgram -> CoreProgram
get [] (Floats -> OrdList FloatingBind
getFloats Floats
floats)
where
get :: FloatingBind -> CoreProgram -> CoreProgram
get (Float CoreBind
b BindInfo
_ FloatInfo
TopLvlFloatable) CoreProgram
bs
= CoreBind -> CoreBind
get_bind CoreBind
b CoreBind -> CoreProgram -> CoreProgram
forall a. a -> [a] -> [a]
: CoreProgram
bs
get FloatingBind
b CoreProgram
_ = String -> SDoc -> CoreProgram
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"corePrepPgm" (FloatingBind -> SDoc
forall a. Outputable a => a -> SDoc
ppr FloatingBind
b)
get_bind :: CoreBind -> CoreBind
get_bind (NonRec InVar
x CpeRhs
e) = InVar -> CpeRhs -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec InVar
x (CpeRhs -> CpeRhs
occurAnalyseExpr CpeRhs
e)
get_bind (Rec [(InVar, CpeRhs)]
xes) = [(InVar, CpeRhs)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec [(InVar
x, CpeRhs -> CpeRhs
occurAnalyseExpr CpeRhs
e) | (InVar
x, CpeRhs
e) <- [(InVar, CpeRhs)]
xes]
data FloatDecision
= FloatNone
| FloatAll
executeFloatDecision :: FloatDecision -> Floats -> CpeRhs -> UniqSM (Floats, CpeRhs)
executeFloatDecision :: FloatDecision -> Floats -> CpeRhs -> UniqSM (Floats, CpeRhs)
executeFloatDecision FloatDecision
dec Floats
floats CpeRhs
rhs
= case FloatDecision
dec of
FloatDecision
FloatAll -> (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
floats, CpeRhs
rhs)
FloatDecision
FloatNone
| Floats -> Bool
isEmptyFloats Floats
floats -> (Floats, CpeRhs) -> UniqSM (Floats, CpeRhs)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (Floats
emptyFloats, CpeRhs
rhs)
| Bool
otherwise -> do { (floats', body) <- CpeRhs -> UniqSM (Floats, CpeRhs)
rhsToBody CpeRhs
rhs
; return (emptyFloats, wrapBinds floats $
wrapBinds floats' body) }
wantFloatTop :: Floats -> FloatDecision
wantFloatTop :: Floats -> FloatDecision
wantFloatTop Floats
fs
| Floats -> FloatInfo
fs_info Floats
fs FloatInfo -> FloatInfo -> Bool
`floatsAtLeastAsFarAs` FloatInfo
TopLvlFloatable = FloatDecision
FloatAll
| Bool
otherwise = FloatDecision
FloatNone
wantFloatLocal :: RecFlag -> Demand -> Bool -> Floats -> CpeRhs -> FloatDecision
wantFloatLocal :: RecFlag -> Demand -> Bool -> Floats -> CpeRhs -> FloatDecision
wantFloatLocal RecFlag
is_rec Demand
rhs_dmd Bool
rhs_is_unlifted Floats
floats CpeRhs
rhs
| Floats -> Bool
isEmptyFloats Floats
floats
Bool -> Bool -> Bool
|| Demand -> Bool
isStrUsedDmd Demand
rhs_dmd
Bool -> Bool -> Bool
|| Bool
rhs_is_unlifted
Bool -> Bool -> Bool
|| (Floats -> FloatInfo
fs_info Floats
floats FloatInfo -> FloatInfo -> Bool
`floatsAtLeastAsFarAs` FloatInfo
max_float_info Bool -> Bool -> Bool
&& CpeRhs -> Bool
exprIsHNF CpeRhs
rhs)
= FloatDecision
FloatAll
| Bool
otherwise
= FloatDecision
FloatNone
where
max_float_info :: FloatInfo
max_float_info | RecFlag -> Bool
isRec RecFlag
is_rec = FloatInfo
TopLvlFloatable
| Bool
otherwise = FloatInfo
LazyContextFloatable
data CorePrepConfig = CorePrepConfig
{ CorePrepConfig -> Bool
cp_catchNonexhaustiveCases :: !Bool
, CorePrepConfig -> LitNumType -> Integer -> Maybe CpeRhs
cp_convertNumLit :: !(LitNumType -> Integer -> Maybe CoreExpr)
, CorePrepConfig -> Maybe ArityOpts
cp_arityOpts :: !(Maybe ArityOpts)
}
data CorePrepEnv
= CPE { CorePrepEnv -> CorePrepConfig
cpe_config :: !CorePrepConfig
, CorePrepEnv -> Subst
cpe_subst :: Subst
, CorePrepEnv -> UnVarSet
cpe_rec_ids :: UnVarSet
}
mkInitialCorePrepEnv :: CorePrepConfig -> CorePrepEnv
mkInitialCorePrepEnv :: CorePrepConfig -> CorePrepEnv
mkInitialCorePrepEnv CorePrepConfig
cfg = CPE
{ cpe_config :: CorePrepConfig
cpe_config = CorePrepConfig
cfg
, cpe_subst :: Subst
cpe_subst = Subst
emptySubst
, cpe_rec_ids :: UnVarSet
cpe_rec_ids = UnVarSet
emptyUnVarSet
}
extendCorePrepEnv :: CorePrepEnv -> Id -> Id -> CorePrepEnv
extendCorePrepEnv :: CorePrepEnv -> InVar -> InVar -> CorePrepEnv
extendCorePrepEnv cpe :: CorePrepEnv
cpe@(CPE { cpe_subst :: CorePrepEnv -> Subst
cpe_subst = Subst
subst }) InVar
id InVar
id'
= CorePrepEnv
cpe { cpe_subst = subst2 }
where
subst1 :: Subst
subst1 = Subst -> InVar -> Subst
extendSubstInScope Subst
subst InVar
id'
subst2 :: Subst
subst2 = Subst -> InVar -> CpeRhs -> Subst
extendIdSubst Subst
subst1 InVar
id (InVar -> CpeRhs
forall b. InVar -> Expr b
Var InVar
id')
extendCorePrepEnvList :: CorePrepEnv -> [(Id,Id)] -> CorePrepEnv
extendCorePrepEnvList :: CorePrepEnv -> [(InVar, InVar)] -> CorePrepEnv
extendCorePrepEnvList cpe :: CorePrepEnv
cpe@(CPE { cpe_subst :: CorePrepEnv -> Subst
cpe_subst = Subst
subst }) [(InVar, InVar)]
prs
= CorePrepEnv
cpe { cpe_subst = subst2 }
where
subst1 :: Subst
subst1 = Subst -> [InVar] -> Subst
extendSubstInScopeList Subst
subst (((InVar, InVar) -> InVar) -> [(InVar, InVar)] -> [InVar]
forall a b. (a -> b) -> [a] -> [b]
map (InVar, InVar) -> InVar
forall a b. (a, b) -> b
snd [(InVar, InVar)]
prs)
subst2 :: Subst
subst2 = Subst -> [(InVar, CpeRhs)] -> Subst
extendIdSubstList Subst
subst1 [(InVar
id, InVar -> CpeRhs
forall b. InVar -> Expr b
Var InVar
id') | (InVar
id,InVar
id') <- [(InVar, InVar)]
prs]
extendCorePrepEnvExpr :: CorePrepEnv -> Id -> CoreExpr -> CorePrepEnv
extendCorePrepEnvExpr :: CorePrepEnv -> InVar -> CpeRhs -> CorePrepEnv
extendCorePrepEnvExpr CorePrepEnv
cpe InVar
id CpeRhs
expr
= CorePrepEnv
cpe { cpe_subst = extendIdSubst (cpe_subst cpe) id expr }
lookupCorePrepEnv :: CorePrepEnv -> Id -> CoreExpr
lookupCorePrepEnv :: CorePrepEnv -> InVar -> CpeRhs
lookupCorePrepEnv CorePrepEnv
cpe InVar
id
= case HasDebugCallStack => Subst -> InVar -> Maybe CpeRhs
Subst -> InVar -> Maybe CpeRhs
lookupIdSubst_maybe (CorePrepEnv -> Subst
cpe_subst CorePrepEnv
cpe) InVar
id of
Just CpeRhs
e -> CpeRhs
e
Maybe CpeRhs
Nothing -> InVar -> CpeRhs
forall b. InVar -> Expr b
Var InVar
id
enterRecGroupRHSs :: CorePrepEnv -> [OutId] -> CorePrepEnv
enterRecGroupRHSs :: CorePrepEnv -> [InVar] -> CorePrepEnv
enterRecGroupRHSs CorePrepEnv
env [InVar]
grp
= CorePrepEnv
env { cpe_rec_ids = extendUnVarSetList grp (cpe_rec_ids env) }
cpSubstTy :: CorePrepEnv -> Type -> Type
cpSubstTy :: CorePrepEnv -> Type -> Type
cpSubstTy (CPE { cpe_subst :: CorePrepEnv -> Subst
cpe_subst = Subst
subst }) Type
ty = HasDebugCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst Type
ty
cpSubstCo :: CorePrepEnv -> Coercion -> Coercion
cpSubstCo :: CorePrepEnv -> Coercion -> Coercion
cpSubstCo (CPE { cpe_subst :: CorePrepEnv -> Subst
cpe_subst = Subst
subst }) Coercion
co = HasDebugCallStack => Subst -> Coercion -> Coercion
Subst -> Coercion -> Coercion
substCo Subst
subst Coercion
co
cpCloneBndrs :: CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [OutVar])
cpCloneBndrs :: CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [InVar])
cpCloneBndrs CorePrepEnv
env [InVar]
bs = (CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, InVar))
-> CorePrepEnv -> [InVar] -> UniqSM (CorePrepEnv, [InVar])
forall (m :: * -> *) (t :: * -> *) acc x y.
(Monad m, Traversable t) =>
(acc -> x -> m (acc, y)) -> acc -> t x -> m (acc, t y)
mapAccumLM CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, InVar)
cpCloneBndr CorePrepEnv
env [InVar]
bs
cpCloneCoVarBndr :: CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, OutVar)
cpCloneCoVarBndr :: CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, InVar)
cpCloneCoVarBndr env :: CorePrepEnv
env@(CPE { cpe_subst :: CorePrepEnv -> Subst
cpe_subst = Subst
subst }) InVar
covar
= Bool
-> SDoc
-> UniqSM (CorePrepEnv, InVar)
-> UniqSM (CorePrepEnv, InVar)
forall a. HasCallStack => Bool -> SDoc -> a -> a
assertPpr (InVar -> Bool
isCoVar InVar
covar) (InVar -> SDoc
forall a. Outputable a => a -> SDoc
ppr InVar
covar) (UniqSM (CorePrepEnv, InVar) -> UniqSM (CorePrepEnv, InVar))
-> UniqSM (CorePrepEnv, InVar) -> UniqSM (CorePrepEnv, InVar)
forall a b. (a -> b) -> a -> b
$
do { uniq <- UniqSM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let covar1 = InVar -> Unique -> InVar
setVarUnique InVar
covar Unique
uniq
covar2 = (Type -> Type) -> InVar -> InVar
updateVarType (HasDebugCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst) InVar
covar1
subst1 = Subst -> InVar -> InVar -> Subst
extendTCvSubstWithClone Subst
subst InVar
covar InVar
covar2
; return (env { cpe_subst = subst1 }, covar2) }
cpCloneBndr :: CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, OutVar)
cpCloneBndr :: CorePrepEnv -> InVar -> UniqSM (CorePrepEnv, InVar)
cpCloneBndr env :: CorePrepEnv
env@(CPE { cpe_subst :: CorePrepEnv -> Subst
cpe_subst = Subst
subst }) InVar
bndr
| InVar -> Bool
isTyCoVar InVar
bndr
= if Subst -> Bool
isEmptyTCvSubst Subst
subst
then (CorePrepEnv, InVar) -> UniqSM (CorePrepEnv, InVar)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (CorePrepEnv
env { cpe_subst = extendSubstInScope subst bndr }, InVar
bndr)
else
let bndr1 :: InVar
bndr1 = (Type -> Type) -> InVar -> InVar
updateVarType (HasDebugCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst) InVar
bndr
subst1 :: Subst
subst1 = Subst -> InVar -> InVar -> Subst
extendTCvSubstWithClone Subst
subst InVar
bndr InVar
bndr1
in (CorePrepEnv, InVar) -> UniqSM (CorePrepEnv, InVar)
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return (CorePrepEnv
env { cpe_subst = subst1 }, InVar
bndr1)
| Bool
otherwise
= do { bndr1 <- InVar -> UniqSM InVar
forall {m :: * -> *}. MonadUnique m => InVar -> m InVar
clone_it InVar
bndr
; let bndr2 = (Type -> Type) -> InVar -> InVar
updateIdTypeAndMult (HasDebugCallStack => Subst -> Type -> Type
Subst -> Type -> Type
substTy Subst
subst) InVar
bndr1
; let !unfolding' = Unfolding -> Unfolding
trimUnfolding (InVar -> Unfolding
realIdUnfolding InVar
bndr)
bndr3 = InVar
bndr2 InVar -> Unfolding -> InVar
`setIdUnfolding` Unfolding
unfolding'
InVar -> RuleInfo -> InVar
`setIdSpecialisation` RuleInfo
emptyRuleInfo
; return (extendCorePrepEnv env bndr bndr3, bndr3) }
where
clone_it :: InVar -> m InVar
clone_it InVar
bndr
| InVar -> Bool
isLocalId InVar
bndr
= do { uniq <- m Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; return (setVarUnique bndr uniq) }
| Bool
otherwise
= InVar -> m InVar
forall a. a -> m a
forall (m :: * -> *) a. Monad m => a -> m a
return InVar
bndr
fiddleCCall :: Id -> UniqSM Id
fiddleCCall :: InVar -> UniqSM InVar
fiddleCCall InVar
id
| InVar -> Bool
isFCallId InVar
id = (InVar
id InVar -> Unique -> InVar
`setVarUnique`) (Unique -> InVar) -> UniqSM Unique -> UniqSM InVar
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> UniqSM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
| Bool
otherwise = InVar -> UniqSM InVar
forall a. a -> UniqSM a
forall (m :: * -> *) a. Monad m => a -> m a
return InVar
id
newVar :: Type -> UniqSM Id
newVar :: Type -> UniqSM InVar
newVar Type
ty
= Type -> ()
seqType Type
ty () -> UniqSM InVar -> UniqSM InVar
forall a b. a -> b -> b
`seq` FastString -> Type -> Type -> UniqSM InVar
forall (m :: * -> *).
MonadUnique m =>
FastString -> Type -> Type -> m InVar
mkSysLocalOrCoVarM (String -> FastString
fsLit String
"sat") Type
ManyTy Type
ty
wrapTicks :: Floats -> CoreExpr -> (Floats, CoreExpr)
wrapTicks :: Floats -> CpeRhs -> (Floats, CpeRhs)
wrapTicks Floats
floats CpeRhs
expr
| (Floats
floats1, OrdList CoreTickish
ticks1) <- ((OrdList FloatingBind, OrdList CoreTickish)
-> FloatingBind -> (OrdList FloatingBind, OrdList CoreTickish))
-> Floats -> (Floats, OrdList CoreTickish)
forall {a}.
((OrdList FloatingBind, OrdList a)
-> FloatingBind -> (OrdList FloatingBind, OrdList a))
-> Floats -> (Floats, OrdList a)
fold_fun (OrdList FloatingBind, OrdList CoreTickish)
-> FloatingBind -> (OrdList FloatingBind, OrdList CoreTickish)
go Floats
floats
= (Floats
floats1, (CoreTickish -> CpeRhs -> CpeRhs)
-> CpeRhs -> OrdList CoreTickish -> CpeRhs
forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL CoreTickish -> CpeRhs -> CpeRhs
mkTick CpeRhs
expr OrdList CoreTickish
ticks1)
where fold_fun :: ((OrdList FloatingBind, OrdList a)
-> FloatingBind -> (OrdList FloatingBind, OrdList a))
-> Floats -> (Floats, OrdList a)
fold_fun (OrdList FloatingBind, OrdList a)
-> FloatingBind -> (OrdList FloatingBind, OrdList a)
f Floats
floats =
let (OrdList FloatingBind
binds, OrdList a
ticks) = ((OrdList FloatingBind, OrdList a)
-> FloatingBind -> (OrdList FloatingBind, OrdList a))
-> (OrdList FloatingBind, OrdList a)
-> OrdList FloatingBind
-> (OrdList FloatingBind, OrdList a)
forall b a. (b -> a -> b) -> b -> OrdList a -> b
foldlOL (OrdList FloatingBind, OrdList a)
-> FloatingBind -> (OrdList FloatingBind, OrdList a)
f (OrdList FloatingBind
forall a. OrdList a
nilOL,OrdList a
forall a. OrdList a
nilOL) (Floats -> OrdList FloatingBind
fs_binds Floats
floats)
in (Floats
floats { fs_binds = binds }, OrdList a
ticks)
go :: (OrdList FloatingBind, OrdList CoreTickish)
-> FloatingBind -> (OrdList FloatingBind, OrdList CoreTickish)
go (OrdList FloatingBind
flt_binds, OrdList CoreTickish
ticks) (FloatTick CoreTickish
t)
= Bool
-> (OrdList FloatingBind, OrdList CoreTickish)
-> (OrdList FloatingBind, OrdList CoreTickish)
forall a. HasCallStack => Bool -> a -> a
assert (CoreTickish -> TickishPlacement
forall (pass :: TickishPass). GenTickish pass -> TickishPlacement
tickishPlace CoreTickish
t TickishPlacement -> TickishPlacement -> Bool
forall a. Eq a => a -> a -> Bool
== TickishPlacement
PlaceNonLam)
(OrdList FloatingBind
flt_binds, if (CoreTickish -> Bool) -> OrdList CoreTickish -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any ((CoreTickish -> CoreTickish -> Bool)
-> CoreTickish -> CoreTickish -> Bool
forall a b c. (a -> b -> c) -> b -> a -> c
flip CoreTickish -> CoreTickish -> Bool
forall (pass :: TickishPass).
Eq (GenTickish pass) =>
GenTickish pass -> GenTickish pass -> Bool
tickishContains CoreTickish
t) OrdList CoreTickish
ticks
then OrdList CoreTickish
ticks else OrdList CoreTickish
ticks OrdList CoreTickish -> CoreTickish -> OrdList CoreTickish
forall a. OrdList a -> a -> OrdList a
`snocOL` CoreTickish
t)
go (OrdList FloatingBind
flt_binds, OrdList CoreTickish
ticks) f :: FloatingBind
f@UnsafeEqualityCase{}
= (OrdList FloatingBind
flt_binds OrdList FloatingBind -> FloatingBind -> OrdList FloatingBind
forall a. OrdList a -> a -> OrdList a
`snocOL` FloatingBind
f, OrdList CoreTickish
ticks)
go (OrdList FloatingBind
flt_binds, OrdList CoreTickish
ticks) f :: FloatingBind
f@Float{}
= (OrdList FloatingBind
flt_binds OrdList FloatingBind -> FloatingBind -> OrdList FloatingBind
forall a. OrdList a -> a -> OrdList a
`snocOL` (CoreTickish -> FloatingBind -> FloatingBind)
-> FloatingBind -> OrdList CoreTickish -> FloatingBind
forall a b. (a -> b -> b) -> b -> OrdList a -> b
foldrOL CoreTickish -> FloatingBind -> FloatingBind
wrap FloatingBind
f OrdList CoreTickish
ticks, OrdList CoreTickish
ticks)
wrap :: CoreTickish -> FloatingBind -> FloatingBind
wrap CoreTickish
t (Float CoreBind
bind BindInfo
bound FloatInfo
info) = CoreBind -> BindInfo -> FloatInfo -> FloatingBind
Float (CoreTickish -> CoreBind -> CoreBind
wrapBind CoreTickish
t CoreBind
bind) BindInfo
bound FloatInfo
info
wrap CoreTickish
_ FloatingBind
f = String -> SDoc -> FloatingBind
forall a. HasCallStack => String -> SDoc -> a
pprPanic String
"Unexpected FloatingBind" (FloatingBind -> SDoc
forall a. Outputable a => a -> SDoc
ppr FloatingBind
f)
wrapBind :: CoreTickish -> CoreBind -> CoreBind
wrapBind CoreTickish
t (NonRec InVar
binder CpeRhs
rhs) = InVar -> CpeRhs -> CoreBind
forall b. b -> Expr b -> Bind b
NonRec InVar
binder (CoreTickish -> CpeRhs -> CpeRhs
mkTick CoreTickish
t CpeRhs
rhs)
wrapBind CoreTickish
t (Rec [(InVar, CpeRhs)]
pairs) = [(InVar, CpeRhs)] -> CoreBind
forall b. [(b, Expr b)] -> Bind b
Rec ((CpeRhs -> CpeRhs) -> [(InVar, CpeRhs)] -> [(InVar, CpeRhs)]
forall (f :: * -> *) b c a.
Functor f =>
(b -> c) -> f (a, b) -> f (a, c)
mapSnd (CoreTickish -> CpeRhs -> CpeRhs
mkTick CoreTickish
t) [(InVar, CpeRhs)]
pairs)
mkConvertNumLiteral
:: Platform
-> HomeUnit
-> (Name -> IO TyThing)
-> IO (LitNumType -> Integer -> Maybe CoreExpr)
mkConvertNumLiteral :: Platform
-> HomeUnit
-> (Name -> IO TyThing)
-> IO (LitNumType -> Integer -> Maybe CpeRhs)
mkConvertNumLiteral Platform
platform HomeUnit
home_unit Name -> IO TyThing
lookup_global = do
let
guardBignum :: IO InVar -> IO InVar
guardBignum IO InVar
act
| HomeUnit -> UnitId -> Bool
isHomeUnitInstanceOf HomeUnit
home_unit UnitId
primUnitId
= InVar -> IO InVar
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (InVar -> IO InVar) -> InVar -> IO InVar
forall a b. (a -> b) -> a -> b
$ String -> InVar
forall a. HasCallStack => String -> a
panic String
"Bignum literals are not supported in ghc-prim"
| HomeUnit -> UnitId -> Bool
isHomeUnitInstanceOf HomeUnit
home_unit UnitId
bignumUnitId
= InVar -> IO InVar
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return (InVar -> IO InVar) -> InVar -> IO InVar
forall a b. (a -> b) -> a -> b
$ String -> InVar
forall a. HasCallStack => String -> a
panic String
"Bignum literals are not supported in ghc-bignum"
| Bool
otherwise = IO InVar
act
lookupBignumId :: Name -> IO InVar
lookupBignumId Name
n = IO InVar -> IO InVar
guardBignum (HasDebugCallStack => TyThing -> InVar
TyThing -> InVar
tyThingId (TyThing -> InVar) -> IO TyThing -> IO InVar
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Name -> IO TyThing
lookup_global Name
n)
bignatFromWordListId <- Name -> IO InVar
lookupBignumId Name
bignatFromWordListName
let
convertNumLit LitNumType
nt Integer
i = case LitNumType
nt of
LitNumType
LitNumBigNat -> CpeRhs -> Maybe CpeRhs
forall a. a -> Maybe a
Just (Integer -> CpeRhs
convertBignatPrim Integer
i)
LitNumType
_ -> Maybe CpeRhs
forall a. Maybe a
Nothing
convertBignatPrim Integer
i =
let
words :: CpeRhs
words = Type -> [CpeRhs] -> CpeRhs
mkListExpr Type
wordTy ([CpeRhs] -> [CpeRhs]
forall a. [a] -> [a]
reverse ((Integer -> Maybe (CpeRhs, Integer)) -> Integer -> [CpeRhs]
forall b a. (b -> Maybe (a, b)) -> b -> [a]
unfoldr Integer -> Maybe (CpeRhs, Integer)
f Integer
i))
where
f :: Integer -> Maybe (CpeRhs, Integer)
f Integer
0 = Maybe (CpeRhs, Integer)
forall a. Maybe a
Nothing
f Integer
x = let low :: Integer
low = Integer
x Integer -> Integer -> Integer
forall a. Bits a => a -> a -> a
.&. Integer
mask
high :: Integer
high = Integer
x Integer -> Int -> Integer
forall a. Bits a => a -> Int -> a
`shiftR` Int
bits
in (CpeRhs, Integer) -> Maybe (CpeRhs, Integer)
forall a. a -> Maybe a
Just (DataCon -> [CpeRhs] -> CpeRhs
forall b. DataCon -> [Arg b] -> Arg b
mkConApp DataCon
wordDataCon [Literal -> CpeRhs
forall b. Literal -> Expr b
Lit (Platform -> Integer -> Literal
mkLitWord Platform
platform Integer
low)], Integer
high)
bits :: Int
bits = Platform -> Int
platformWordSizeInBits Platform
platform
mask :: Integer
mask = Integer
2 Integer -> Int -> Integer
forall a b. (Num a, Integral b) => a -> b -> a
^ Int
bits Integer -> Integer -> Integer
forall a. Num a => a -> a -> a
- Integer
1
in CpeRhs -> [CpeRhs] -> CpeRhs
forall b. Expr b -> [Expr b] -> Expr b
mkApps (InVar -> CpeRhs
forall b. InVar -> Expr b
Var InVar
bignatFromWordListId) [CpeRhs
words]
return convertNumLit