{-# LANGUAGE CPP #-}
module Specialise ( specProgram, specUnfolding ) where
#include "HsVersions.h"
import GhcPrelude
import Id
import TcType hiding( substTy )
import Type hiding( substTy, extendTvSubstList )
import Module( Module, HasModule(..) )
import Coercion( Coercion )
import CoreMonad
import qualified CoreSubst
import CoreUnfold
import Var ( isLocalVar )
import VarSet
import VarEnv
import CoreSyn
import Rules
import CoreOpt ( collectBindersPushingCo )
import CoreUtils ( exprIsTrivial, applyTypeToArgs, mkCast )
import CoreFVs
import CoreArity ( etaExpandToJoinPointRule )
import UniqSupply
import Name
import MkId ( voidArgId, voidPrimId )
import Maybes ( catMaybes, isJust )
import MonadUtils ( foldlM )
import BasicTypes
import HscTypes
import Bag
import DynFlags
import Util
import Outputable
import FastString
import State
import UniqDFM
import Control.Monad
import qualified Control.Monad.Fail as MonadFail
specProgram :: ModGuts -> CoreM ModGuts
specProgram :: ModGuts -> CoreM ModGuts
specProgram guts :: ModGuts
guts@(ModGuts { mg_module :: ModGuts -> Module
mg_module = Module
this_mod
, mg_rules :: ModGuts -> [CoreRule]
mg_rules = [CoreRule]
local_rules
, mg_binds :: ModGuts -> CoreProgram
mg_binds = CoreProgram
binds })
= do { DynFlags
dflags <- CoreM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; (binds' :: CoreProgram
binds', uds :: UsageDetails
uds) <- DynFlags
-> Module
-> SpecM (CoreProgram, UsageDetails)
-> CoreM (CoreProgram, UsageDetails)
forall a. DynFlags -> Module -> SpecM a -> CoreM a
runSpecM DynFlags
dflags Module
this_mod (CoreProgram -> SpecM (CoreProgram, UsageDetails)
go CoreProgram
binds)
; RuleBase
hpt_rules <- CoreM RuleBase
getRuleBase
; let rule_base :: RuleBase
rule_base = RuleBase -> [CoreRule] -> RuleBase
extendRuleBaseList RuleBase
hpt_rules [CoreRule]
local_rules
; (new_rules :: [CoreRule]
new_rules, spec_binds :: CoreProgram
spec_binds) <- DynFlags
-> Module
-> SpecEnv
-> VarSet
-> [Id]
-> RuleBase
-> UsageDetails
-> CoreM ([CoreRule], CoreProgram)
specImports DynFlags
dflags Module
this_mod SpecEnv
top_env VarSet
emptyVarSet
[] RuleBase
rule_base UsageDetails
uds
; let final_binds :: CoreProgram
final_binds
| CoreProgram -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null CoreProgram
spec_binds = CoreProgram
binds'
| Bool
otherwise = [(Id, Expr Id)] -> Bind Id
forall b. [(b, Expr b)] -> Bind b
Rec (CoreProgram -> [(Id, Expr Id)]
forall b. [Bind b] -> [(b, Expr b)]
flattenBinds CoreProgram
spec_binds) Bind Id -> CoreProgram -> CoreProgram
forall a. a -> [a] -> [a]
: CoreProgram
binds'
; ModGuts -> CoreM ModGuts
forall (m :: * -> *) a. Monad m => a -> m a
return (ModGuts
guts { mg_binds :: CoreProgram
mg_binds = CoreProgram
final_binds
, mg_rules :: [CoreRule]
mg_rules = [CoreRule]
new_rules [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
++ [CoreRule]
local_rules }) }
where
top_env :: SpecEnv
top_env = SE :: Subst -> VarSet -> SpecEnv
SE { se_subst :: Subst
se_subst = InScopeSet -> Subst
CoreSubst.mkEmptySubst (InScopeSet -> Subst) -> InScopeSet -> Subst
forall a b. (a -> b) -> a -> b
$ VarSet -> InScopeSet
mkInScopeSet (VarSet -> InScopeSet) -> VarSet -> InScopeSet
forall a b. (a -> b) -> a -> b
$ [Id] -> VarSet
mkVarSet ([Id] -> VarSet) -> [Id] -> VarSet
forall a b. (a -> b) -> a -> b
$
CoreProgram -> [Id]
forall b. [Bind b] -> [b]
bindersOfBinds CoreProgram
binds
, se_interesting :: VarSet
se_interesting = VarSet
emptyVarSet }
go :: CoreProgram -> SpecM (CoreProgram, UsageDetails)
go [] = (CoreProgram, UsageDetails) -> SpecM (CoreProgram, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], UsageDetails
emptyUDs)
go (bind :: Bind Id
bind:binds :: CoreProgram
binds) = do (binds' :: CoreProgram
binds', uds :: UsageDetails
uds) <- CoreProgram -> SpecM (CoreProgram, UsageDetails)
go CoreProgram
binds
(bind' :: CoreProgram
bind', uds' :: UsageDetails
uds') <- SpecEnv
-> Bind Id -> UsageDetails -> SpecM (CoreProgram, UsageDetails)
specBind SpecEnv
top_env Bind Id
bind UsageDetails
uds
(CoreProgram, UsageDetails) -> SpecM (CoreProgram, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (CoreProgram
bind' CoreProgram -> CoreProgram -> CoreProgram
forall a. [a] -> [a] -> [a]
++ CoreProgram
binds', UsageDetails
uds')
specImports :: DynFlags
-> Module
-> SpecEnv
-> VarSet
-> [Id]
-> RuleBase
-> UsageDetails
-> CoreM ( [CoreRule]
, [CoreBind] )
specImports :: DynFlags
-> Module
-> SpecEnv
-> VarSet
-> [Id]
-> RuleBase
-> UsageDetails
-> CoreM ([CoreRule], CoreProgram)
specImports dflags :: DynFlags
dflags this_mod :: Module
this_mod top_env :: SpecEnv
top_env done :: VarSet
done callers :: [Id]
callers rule_base :: RuleBase
rule_base
(MkUD { ud_binds :: UsageDetails -> Bag DictBind
ud_binds = Bag DictBind
dict_binds, ud_calls :: UsageDetails -> CallDetails
ud_calls = CallDetails
calls })
| Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_CrossModuleSpecialise DynFlags
dflags
= ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [])
| Bool
otherwise
= do { let import_calls :: [CallInfoSet]
import_calls = CallDetails -> [CallInfoSet]
forall a. DVarEnv a -> [a]
dVarEnvElts CallDetails
calls
; (rules :: [CoreRule]
rules, spec_binds :: CoreProgram
spec_binds) <- RuleBase -> [CallInfoSet] -> CoreM ([CoreRule], CoreProgram)
go RuleBase
rule_base [CallInfoSet]
import_calls
; let spec_binds' :: CoreProgram
spec_binds' = Bag DictBind -> CoreProgram -> CoreProgram
wrapDictBinds Bag DictBind
dict_binds CoreProgram
spec_binds
; ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([CoreRule]
rules, CoreProgram
spec_binds') }
where
go :: RuleBase -> [CallInfoSet] -> CoreM ([CoreRule], [CoreBind])
go :: RuleBase -> [CallInfoSet] -> CoreM ([CoreRule], CoreProgram)
go _ [] = ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [])
go rb :: RuleBase
rb (cis :: CallInfoSet
cis@(CIS fn :: Id
fn _) : other_calls :: [CallInfoSet]
other_calls)
= do { let ok_calls :: [CallInfo]
ok_calls = CallInfoSet -> Bag DictBind -> [CallInfo]
filterCalls CallInfoSet
cis Bag DictBind
dict_binds
; (rules1 :: [CoreRule]
rules1, spec_binds1 :: CoreProgram
spec_binds1) <- DynFlags
-> Module
-> SpecEnv
-> VarSet
-> [Id]
-> RuleBase
-> Id
-> [CallInfo]
-> CoreM ([CoreRule], CoreProgram)
specImport DynFlags
dflags Module
this_mod SpecEnv
top_env
VarSet
done [Id]
callers RuleBase
rb Id
fn [CallInfo]
ok_calls
; (rules2 :: [CoreRule]
rules2, spec_binds2 :: CoreProgram
spec_binds2) <- RuleBase -> [CallInfoSet] -> CoreM ([CoreRule], CoreProgram)
go (RuleBase -> [CoreRule] -> RuleBase
extendRuleBaseList RuleBase
rb [CoreRule]
rules1) [CallInfoSet]
other_calls
; ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([CoreRule]
rules1 [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
++ [CoreRule]
rules2, CoreProgram
spec_binds1 CoreProgram -> CoreProgram -> CoreProgram
forall a. [a] -> [a] -> [a]
++ CoreProgram
spec_binds2) }
specImport :: DynFlags
-> Module
-> SpecEnv
-> VarSet
-> [Id]
-> RuleBase
-> Id -> [CallInfo]
-> CoreM ( [CoreRule]
, [CoreBind] )
specImport :: DynFlags
-> Module
-> SpecEnv
-> VarSet
-> [Id]
-> RuleBase
-> Id
-> [CallInfo]
-> CoreM ([CoreRule], CoreProgram)
specImport dflags :: DynFlags
dflags this_mod :: Module
this_mod top_env :: SpecEnv
top_env done :: VarSet
done callers :: [Id]
callers rb :: RuleBase
rb fn :: Id
fn calls_for_fn :: [CallInfo]
calls_for_fn
| Id
fn Id -> VarSet -> Bool
`elemVarSet` VarSet
done
= ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [])
| [CallInfo] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [CallInfo]
calls_for_fn
= ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [])
| DynFlags -> Unfolding -> Bool
wantSpecImport DynFlags
dflags Unfolding
unfolding
, Just rhs :: Expr Id
rhs <- Unfolding -> Maybe (Expr Id)
maybeUnfoldingTemplate Unfolding
unfolding
= do {
; HscEnv
hsc_env <- CoreM HscEnv
getHscEnv
; ExternalPackageState
eps <- IO ExternalPackageState -> CoreM ExternalPackageState
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO ExternalPackageState -> CoreM ExternalPackageState)
-> IO ExternalPackageState -> CoreM ExternalPackageState
forall a b. (a -> b) -> a -> b
$ HscEnv -> IO ExternalPackageState
hscEPS HscEnv
hsc_env
; ModuleSet
vis_orphs <- CoreM ModuleSet
getVisibleOrphanMods
; let full_rb :: RuleBase
full_rb = RuleBase -> RuleBase -> RuleBase
unionRuleBase RuleBase
rb (ExternalPackageState -> RuleBase
eps_rule_base ExternalPackageState
eps)
rules_for_fn :: [CoreRule]
rules_for_fn = RuleEnv -> Id -> [CoreRule]
getRules (RuleBase -> ModuleSet -> RuleEnv
RuleEnv RuleBase
full_rb ModuleSet
vis_orphs) Id
fn
; (rules1 :: [CoreRule]
rules1, spec_pairs :: [(Id, Expr Id)]
spec_pairs, uds :: UsageDetails
uds)
<-
DynFlags
-> Module
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> CoreM ([CoreRule], [(Id, Expr Id)], UsageDetails)
forall a. DynFlags -> Module -> SpecM a -> CoreM a
runSpecM DynFlags
dflags Module
this_mod (SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> CoreM ([CoreRule], [(Id, Expr Id)], UsageDetails))
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> CoreM ([CoreRule], [(Id, Expr Id)], UsageDetails)
forall a b. (a -> b) -> a -> b
$
Maybe Module
-> SpecEnv
-> [CoreRule]
-> [CallInfo]
-> Id
-> Expr Id
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
specCalls (Module -> Maybe Module
forall a. a -> Maybe a
Just Module
this_mod) SpecEnv
top_env [CoreRule]
rules_for_fn [CallInfo]
calls_for_fn Id
fn Expr Id
rhs
; let spec_binds1 :: CoreProgram
spec_binds1 = [Id -> Expr Id -> Bind Id
forall b. b -> Expr b -> Bind b
NonRec Id
b Expr Id
r | (b :: Id
b,r :: Expr Id
r) <- [(Id, Expr Id)]
spec_pairs]
; (rules2 :: [CoreRule]
rules2, spec_binds2 :: CoreProgram
spec_binds2) <-
DynFlags
-> Module
-> SpecEnv
-> VarSet
-> [Id]
-> RuleBase
-> UsageDetails
-> CoreM ([CoreRule], CoreProgram)
specImports DynFlags
dflags Module
this_mod SpecEnv
top_env
(VarSet -> Id -> VarSet
extendVarSet VarSet
done Id
fn)
(Id
fnId -> [Id] -> [Id]
forall a. a -> [a] -> [a]
:[Id]
callers)
(RuleBase -> [CoreRule] -> RuleBase
extendRuleBaseList RuleBase
rb [CoreRule]
rules1)
UsageDetails
uds
; let final_binds :: CoreProgram
final_binds = CoreProgram
spec_binds2 CoreProgram -> CoreProgram -> CoreProgram
forall a. [a] -> [a] -> [a]
++ CoreProgram
spec_binds1
; ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([CoreRule]
rules2 [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
++ [CoreRule]
rules1, CoreProgram
final_binds) }
| DynFlags -> [Id] -> Bool
warnMissingSpecs DynFlags
dflags [Id]
callers
= do { SDoc -> CoreM ()
warnMsg ([SDoc] -> SDoc
vcat [ SDoc -> Int -> SDoc -> SDoc
hang (String -> SDoc
text "Could not specialise imported function" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
fn))
2 ([SDoc] -> SDoc
vcat [ String -> SDoc
text "when specialising" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
caller)
| Id
caller <- [Id]
callers])
, SDoc -> SDoc
whenPprDebug (String -> SDoc
text "calls:" SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
vcat ((CallInfo -> SDoc) -> [CallInfo] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map (Id -> CallInfo -> SDoc
pprCallInfo Id
fn) [CallInfo]
calls_for_fn))
, String -> SDoc
text "Probable fix: add INLINABLE pragma on" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
quotes (Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
fn) ])
; ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], []) }
| Bool
otherwise
= ([CoreRule], CoreProgram) -> CoreM ([CoreRule], CoreProgram)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [])
where
unfolding :: Unfolding
unfolding = Id -> Unfolding
realIdUnfolding Id
fn
warnMissingSpecs :: DynFlags -> [Id] -> Bool
warnMissingSpecs :: DynFlags -> [Id] -> Bool
warnMissingSpecs dflags :: DynFlags
dflags callers :: [Id]
callers
| WarningFlag -> DynFlags -> Bool
wopt WarningFlag
Opt_WarnAllMissedSpecs DynFlags
dflags = Bool
True
| Bool -> Bool
not (WarningFlag -> DynFlags -> Bool
wopt WarningFlag
Opt_WarnMissedSpecs DynFlags
dflags) = Bool
False
| [Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Id]
callers = Bool
False
| Bool
otherwise = (Id -> Bool) -> [Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Id -> Bool
has_inline_prag [Id]
callers
where
has_inline_prag :: Id -> Bool
has_inline_prag id :: Id
id = InlinePragma -> Bool
isAnyInlinePragma (Id -> InlinePragma
idInlinePragma Id
id)
wantSpecImport :: DynFlags -> Unfolding -> Bool
wantSpecImport :: DynFlags -> Unfolding -> Bool
wantSpecImport dflags :: DynFlags
dflags unf :: Unfolding
unf
= case Unfolding
unf of
NoUnfolding -> Bool
False
BootUnfolding -> Bool
False
OtherCon {} -> Bool
False
DFunUnfolding {} -> Bool
True
CoreUnfolding { uf_src :: Unfolding -> UnfoldingSource
uf_src = UnfoldingSource
src, uf_guidance :: Unfolding -> UnfoldingGuidance
uf_guidance = UnfoldingGuidance
_guidance }
| GeneralFlag -> DynFlags -> Bool
gopt GeneralFlag
Opt_SpecialiseAggressively DynFlags
dflags -> Bool
True
| UnfoldingSource -> Bool
isStableSource UnfoldingSource
src -> Bool
True
| Bool
otherwise -> Bool
False
data SpecEnv
= SE { SpecEnv -> Subst
se_subst :: CoreSubst.Subst
, SpecEnv -> VarSet
se_interesting :: VarSet
}
specVar :: SpecEnv -> Id -> CoreExpr
specVar :: SpecEnv -> Id -> Expr Id
specVar env :: SpecEnv
env v :: Id
v = SDoc -> Subst -> Id -> Expr Id
CoreSubst.lookupIdSubst (String -> SDoc
text "specVar") (SpecEnv -> Subst
se_subst SpecEnv
env) Id
v
specExpr :: SpecEnv -> CoreExpr -> SpecM (CoreExpr, UsageDetails)
specExpr :: SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr env :: SpecEnv
env (Type ty :: Type
ty) = (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Type -> Expr Id
forall b. Type -> Expr b
Type (SpecEnv -> Type -> Type
substTy SpecEnv
env Type
ty), UsageDetails
emptyUDs)
specExpr env :: SpecEnv
env (Coercion co :: Coercion
co) = (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Coercion -> Expr Id
forall b. Coercion -> Expr b
Coercion (SpecEnv -> Coercion -> Coercion
substCo SpecEnv
env Coercion
co), UsageDetails
emptyUDs)
specExpr env :: SpecEnv
env (Var v :: Id
v) = (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (SpecEnv -> Id -> Expr Id
specVar SpecEnv
env Id
v, UsageDetails
emptyUDs)
specExpr _ (Lit lit :: Literal
lit) = (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Literal -> Expr Id
forall b. Literal -> Expr b
Lit Literal
lit, UsageDetails
emptyUDs)
specExpr env :: SpecEnv
env (Cast e :: Expr Id
e co :: Coercion
co)
= do { (e' :: Expr Id
e', uds :: UsageDetails
uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env Expr Id
e
; (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Expr Id -> Coercion -> Expr Id
mkCast Expr Id
e' (SpecEnv -> Coercion -> Coercion
substCo SpecEnv
env Coercion
co)), UsageDetails
uds) }
specExpr env :: SpecEnv
env (Tick tickish :: Tickish Id
tickish body :: Expr Id
body)
= do { (body' :: Expr Id
body', uds :: UsageDetails
uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env Expr Id
body
; (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Tickish Id -> Expr Id -> Expr Id
forall b. Tickish Id -> Expr b -> Expr b
Tick (SpecEnv -> Tickish Id -> Tickish Id
specTickish SpecEnv
env Tickish Id
tickish) Expr Id
body', UsageDetails
uds) }
specExpr env :: SpecEnv
env expr :: Expr Id
expr@(App {})
= Expr Id -> [Expr Id] -> SpecM (Expr Id, UsageDetails)
go Expr Id
expr []
where
go :: Expr Id -> [Expr Id] -> SpecM (Expr Id, UsageDetails)
go (App fun :: Expr Id
fun arg :: Expr Id
arg) args :: [Expr Id]
args = do (arg' :: Expr Id
arg', uds_arg :: UsageDetails
uds_arg) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env Expr Id
arg
(fun' :: Expr Id
fun', uds_app :: UsageDetails
uds_app) <- Expr Id -> [Expr Id] -> SpecM (Expr Id, UsageDetails)
go Expr Id
fun (Expr Id
arg'Expr Id -> [Expr Id] -> [Expr Id]
forall a. a -> [a] -> [a]
:[Expr Id]
args)
(Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Id -> Expr Id -> Expr Id
forall b. Expr b -> Expr b -> Expr b
App Expr Id
fun' Expr Id
arg', UsageDetails
uds_arg UsageDetails -> UsageDetails -> UsageDetails
`plusUDs` UsageDetails
uds_app)
go (Var f :: Id
f) args :: [Expr Id]
args = case SpecEnv -> Id -> Expr Id
specVar SpecEnv
env Id
f of
Var f' :: Id
f' -> (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Id -> Expr Id
forall b. Id -> Expr b
Var Id
f', SpecEnv -> Id -> [Expr Id] -> UsageDetails
mkCallUDs SpecEnv
env Id
f' [Expr Id]
args)
e' :: Expr Id
e' -> (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Id
e', UsageDetails
emptyUDs)
go other :: Expr Id
other _ = SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env Expr Id
other
specExpr env :: SpecEnv
env e :: Expr Id
e@(Lam _ _) = do
(body' :: Expr Id
body', uds :: UsageDetails
uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env' Expr Id
body
let (free_uds :: UsageDetails
free_uds, dumped_dbs :: Bag DictBind
dumped_dbs) = [Id] -> UsageDetails -> (UsageDetails, Bag DictBind)
dumpUDs [Id]
bndrs' UsageDetails
uds
(Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Id] -> Expr Id -> Expr Id
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
bndrs' (Bag DictBind -> Expr Id -> Expr Id
wrapDictBindsE Bag DictBind
dumped_dbs Expr Id
body'), UsageDetails
free_uds)
where
(bndrs :: [Id]
bndrs, body :: Expr Id
body) = Expr Id -> ([Id], Expr Id)
forall b. Expr b -> ([b], Expr b)
collectBinders Expr Id
e
(env' :: SpecEnv
env', bndrs' :: [Id]
bndrs') = SpecEnv -> [Id] -> (SpecEnv, [Id])
substBndrs SpecEnv
env [Id]
bndrs
specExpr env :: SpecEnv
env (Case scrut :: Expr Id
scrut case_bndr :: Id
case_bndr ty :: Type
ty alts :: [Alt Id]
alts)
= do { (scrut' :: Expr Id
scrut', scrut_uds :: UsageDetails
scrut_uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env Expr Id
scrut
; (scrut'' :: Expr Id
scrut'', case_bndr' :: Id
case_bndr', alts' :: [Alt Id]
alts', alts_uds :: UsageDetails
alts_uds)
<- SpecEnv
-> Expr Id
-> Id
-> [Alt Id]
-> SpecM (Expr Id, Id, [Alt Id], UsageDetails)
specCase SpecEnv
env Expr Id
scrut' Id
case_bndr [Alt Id]
alts
; (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Id -> Id -> Type -> [Alt Id] -> Expr Id
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case Expr Id
scrut'' Id
case_bndr' (SpecEnv -> Type -> Type
substTy SpecEnv
env Type
ty) [Alt Id]
alts'
, UsageDetails
scrut_uds UsageDetails -> UsageDetails -> UsageDetails
`plusUDs` UsageDetails
alts_uds) }
specExpr env :: SpecEnv
env (Let bind :: Bind Id
bind body :: Expr Id
body)
= do {
(rhs_env :: SpecEnv
rhs_env, body_env :: SpecEnv
body_env, bind' :: Bind Id
bind') <- SpecEnv -> Bind Id -> SpecM (SpecEnv, SpecEnv, Bind Id)
cloneBindSM SpecEnv
env Bind Id
bind
; (body' :: Expr Id
body', body_uds :: UsageDetails
body_uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
body_env Expr Id
body
; (binds' :: CoreProgram
binds', uds :: UsageDetails
uds) <- SpecEnv
-> Bind Id -> UsageDetails -> SpecM (CoreProgram, UsageDetails)
specBind SpecEnv
rhs_env Bind Id
bind' UsageDetails
body_uds
; (Expr Id, UsageDetails) -> SpecM (Expr Id, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ((Bind Id -> Expr Id -> Expr Id)
-> Expr Id -> CoreProgram -> Expr Id
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr Bind Id -> Expr Id -> Expr Id
forall b. Bind b -> Expr b -> Expr b
Let Expr Id
body' CoreProgram
binds', UsageDetails
uds) }
specTickish :: SpecEnv -> Tickish Id -> Tickish Id
specTickish :: SpecEnv -> Tickish Id -> Tickish Id
specTickish env :: SpecEnv
env (Breakpoint ix :: Int
ix ids :: [Id]
ids)
= Int -> [Id] -> Tickish Id
forall id. Int -> [id] -> Tickish id
Breakpoint Int
ix [ Id
id' | Id
id <- [Id]
ids, Var id' :: Id
id' <- [SpecEnv -> Id -> Expr Id
specVar SpecEnv
env Id
id]]
specTickish _ other_tickish :: Tickish Id
other_tickish = Tickish Id
other_tickish
specCase :: SpecEnv
-> CoreExpr
-> Id -> [CoreAlt]
-> SpecM ( CoreExpr
, Id
, [CoreAlt]
, UsageDetails)
specCase :: SpecEnv
-> Expr Id
-> Id
-> [Alt Id]
-> SpecM (Expr Id, Id, [Alt Id], UsageDetails)
specCase env :: SpecEnv
env scrut' :: Expr Id
scrut' case_bndr :: Id
case_bndr [(con :: AltCon
con, args :: [Id]
args, rhs :: Expr Id
rhs)]
| Id -> Bool
isDictId Id
case_bndr
, SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
scrut'
, Bool -> Bool
not (Id -> Bool
isDeadBinder Id
case_bndr Bool -> Bool -> Bool
&& [Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Id]
sc_args')
= do { (case_bndr_flt :: Id
case_bndr_flt : sc_args_flt :: [Id]
sc_args_flt) <- (Id -> SpecM Id) -> [Id] -> SpecM [Id]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM Id -> SpecM Id
forall (m :: * -> *). MonadUnique m => Id -> m Id
clone_me (Id
case_bndr' Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
sc_args')
; let sc_rhss :: [Expr Id]
sc_rhss = [ Expr Id -> Id -> Type -> [Alt Id] -> Expr Id
forall b. Expr b -> b -> Type -> [Alt b] -> Expr b
Case (Id -> Expr Id
forall b. Id -> Expr b
Var Id
case_bndr_flt) Id
case_bndr' (Id -> Type
idType Id
sc_arg')
[(AltCon
con, [Id]
args', Id -> Expr Id
forall b. Id -> Expr b
Var Id
sc_arg')]
| Id
sc_arg' <- [Id]
sc_args' ]
mb_sc_flts :: [Maybe DictId]
mb_sc_flts :: [Maybe Id]
mb_sc_flts = (Id -> Maybe Id) -> [Id] -> [Maybe Id]
forall a b. (a -> b) -> [a] -> [b]
map (VarEnv Id -> Id -> Maybe Id
forall a. VarEnv a -> Id -> Maybe a
lookupVarEnv VarEnv Id
clone_env) [Id]
args'
clone_env :: VarEnv Id
clone_env = [Id] -> [Id] -> VarEnv Id
forall a. [Id] -> [a] -> VarEnv a
zipVarEnv [Id]
sc_args' [Id]
sc_args_flt
subst_prs :: [(Id, Expr b)]
subst_prs = (Id
case_bndr, Id -> Expr b
forall b. Id -> Expr b
Var Id
case_bndr_flt)
(Id, Expr b) -> [(Id, Expr b)] -> [(Id, Expr b)]
forall a. a -> [a] -> [a]
: [ (Id
arg, Id -> Expr b
forall b. Id -> Expr b
Var Id
sc_flt)
| (arg :: Id
arg, Just sc_flt :: Id
sc_flt) <- [Id]
args [Id] -> [Maybe Id] -> [(Id, Maybe Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Maybe Id]
mb_sc_flts ]
env_rhs' :: SpecEnv
env_rhs' = SpecEnv
env_rhs { se_subst :: Subst
se_subst = Subst -> [(Id, Expr Id)] -> Subst
CoreSubst.extendIdSubstList (SpecEnv -> Subst
se_subst SpecEnv
env_rhs) [(Id, Expr Id)]
forall b. [(Id, Expr b)]
subst_prs
, se_interesting :: VarSet
se_interesting = SpecEnv -> VarSet
se_interesting SpecEnv
env_rhs VarSet -> [Id] -> VarSet
`extendVarSetList`
(Id
case_bndr_flt Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
sc_args_flt) }
; (rhs' :: Expr Id
rhs', rhs_uds :: UsageDetails
rhs_uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env_rhs' Expr Id
rhs
; let scrut_bind :: DictBind
scrut_bind = Bind Id -> DictBind
mkDB (Id -> Expr Id -> Bind Id
forall b. b -> Expr b -> Bind b
NonRec Id
case_bndr_flt Expr Id
scrut')
case_bndr_set :: VarSet
case_bndr_set = Id -> VarSet
unitVarSet Id
case_bndr_flt
sc_binds :: [DictBind]
sc_binds = [(Id -> Expr Id -> Bind Id
forall b. b -> Expr b -> Bind b
NonRec Id
sc_arg_flt Expr Id
sc_rhs, VarSet
case_bndr_set)
| (sc_arg_flt :: Id
sc_arg_flt, sc_rhs :: Expr Id
sc_rhs) <- [Id]
sc_args_flt [Id] -> [Expr Id] -> [(Id, Expr Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Expr Id]
sc_rhss ]
flt_binds :: [DictBind]
flt_binds = DictBind
scrut_bind DictBind -> [DictBind] -> [DictBind]
forall a. a -> [a] -> [a]
: [DictBind]
sc_binds
(free_uds :: UsageDetails
free_uds, dumped_dbs :: Bag DictBind
dumped_dbs) = [Id] -> UsageDetails -> (UsageDetails, Bag DictBind)
dumpUDs (Id
case_bndr'Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
:[Id]
args') UsageDetails
rhs_uds
all_uds :: UsageDetails
all_uds = [DictBind]
flt_binds [DictBind] -> UsageDetails -> UsageDetails
`addDictBinds` UsageDetails
free_uds
alt' :: Alt Id
alt' = (AltCon
con, [Id]
args', Bag DictBind -> Expr Id -> Expr Id
wrapDictBindsE Bag DictBind
dumped_dbs Expr Id
rhs')
; (Expr Id, Id, [Alt Id], UsageDetails)
-> SpecM (Expr Id, Id, [Alt Id], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Id -> Expr Id
forall b. Id -> Expr b
Var Id
case_bndr_flt, Id
case_bndr', [Alt Id
alt'], UsageDetails
all_uds) }
where
(env_rhs :: SpecEnv
env_rhs, (case_bndr' :: Id
case_bndr':args' :: [Id]
args')) = SpecEnv -> [Id] -> (SpecEnv, [Id])
substBndrs SpecEnv
env (Id
case_bndrId -> [Id] -> [Id]
forall a. a -> [a] -> [a]
:[Id]
args)
sc_args' :: [Id]
sc_args' = (Id -> Bool) -> [Id] -> [Id]
forall a. (a -> Bool) -> [a] -> [a]
filter Id -> Bool
is_flt_sc_arg [Id]
args'
clone_me :: Id -> m Id
clone_me bndr :: Id
bndr = do { Unique
uniq <- m Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; Id -> m Id
forall (m :: * -> *) a. Monad m => a -> m a
return (OccName -> Unique -> Type -> SrcSpan -> Id
mkUserLocalOrCoVar OccName
occ Unique
uniq Type
ty SrcSpan
loc) }
where
name :: Name
name = Id -> Name
idName Id
bndr
ty :: Type
ty = Id -> Type
idType Id
bndr
occ :: OccName
occ = Name -> OccName
nameOccName Name
name
loc :: SrcSpan
loc = Name -> SrcSpan
forall a. NamedThing a => a -> SrcSpan
getSrcSpan Name
name
arg_set :: VarSet
arg_set = [Id] -> VarSet
mkVarSet [Id]
args'
is_flt_sc_arg :: Id -> Bool
is_flt_sc_arg var :: Id
var = Id -> Bool
isId Id
var
Bool -> Bool -> Bool
&& Bool -> Bool
not (Id -> Bool
isDeadBinder Id
var)
Bool -> Bool -> Bool
&& Type -> Bool
isDictTy Type
var_ty
Bool -> Bool -> Bool
&& Bool -> Bool
not (Type -> VarSet
tyCoVarsOfType Type
var_ty VarSet -> VarSet -> Bool
`intersectsVarSet` VarSet
arg_set)
where
var_ty :: Type
var_ty = Id -> Type
idType Id
var
specCase env :: SpecEnv
env scrut :: Expr Id
scrut case_bndr :: Id
case_bndr alts :: [Alt Id]
alts
= do { (alts' :: [Alt Id]
alts', uds_alts :: UsageDetails
uds_alts) <- (Alt Id -> SpecM (Alt Id, UsageDetails))
-> [Alt Id] -> SpecM ([Alt Id], UsageDetails)
forall a b.
(a -> SpecM (b, UsageDetails)) -> [a] -> SpecM ([b], UsageDetails)
mapAndCombineSM Alt Id -> SpecM (Alt Id, UsageDetails)
forall a.
(a, [Id], Expr Id) -> SpecM ((a, [Id], Expr Id), UsageDetails)
spec_alt [Alt Id]
alts
; (Expr Id, Id, [Alt Id], UsageDetails)
-> SpecM (Expr Id, Id, [Alt Id], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Expr Id
scrut, Id
case_bndr', [Alt Id]
alts', UsageDetails
uds_alts) }
where
(env_alt :: SpecEnv
env_alt, case_bndr' :: Id
case_bndr') = SpecEnv -> Id -> (SpecEnv, Id)
substBndr SpecEnv
env Id
case_bndr
spec_alt :: (a, [Id], Expr Id) -> SpecM ((a, [Id], Expr Id), UsageDetails)
spec_alt (con :: a
con, args :: [Id]
args, rhs :: Expr Id
rhs) = do
(rhs' :: Expr Id
rhs', uds :: UsageDetails
uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
env_rhs Expr Id
rhs
let (free_uds :: UsageDetails
free_uds, dumped_dbs :: Bag DictBind
dumped_dbs) = [Id] -> UsageDetails -> (UsageDetails, Bag DictBind)
dumpUDs (Id
case_bndr' Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
args') UsageDetails
uds
((a, [Id], Expr Id), UsageDetails)
-> SpecM ((a, [Id], Expr Id), UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ((a
con, [Id]
args', Bag DictBind -> Expr Id -> Expr Id
wrapDictBindsE Bag DictBind
dumped_dbs Expr Id
rhs'), UsageDetails
free_uds)
where
(env_rhs :: SpecEnv
env_rhs, args' :: [Id]
args') = SpecEnv -> [Id] -> (SpecEnv, [Id])
substBndrs SpecEnv
env_alt [Id]
args
specBind :: SpecEnv
-> CoreBind
-> UsageDetails
-> SpecM ([CoreBind],
UsageDetails)
specBind :: SpecEnv
-> Bind Id -> UsageDetails -> SpecM (CoreProgram, UsageDetails)
specBind rhs_env :: SpecEnv
rhs_env (NonRec fn :: Id
fn rhs :: Expr Id
rhs) body_uds :: UsageDetails
body_uds
= do { (rhs' :: Expr Id
rhs', rhs_uds :: UsageDetails
rhs_uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
rhs_env Expr Id
rhs
; (fn' :: Id
fn', spec_defns :: [(Id, Expr Id)]
spec_defns, body_uds1 :: UsageDetails
body_uds1) <- SpecEnv
-> UsageDetails
-> Id
-> Expr Id
-> SpecM (Id, [(Id, Expr Id)], UsageDetails)
specDefn SpecEnv
rhs_env UsageDetails
body_uds Id
fn Expr Id
rhs
; let pairs :: [(Id, Expr Id)]
pairs = [(Id, Expr Id)]
spec_defns [(Id, Expr Id)] -> [(Id, Expr Id)] -> [(Id, Expr Id)]
forall a. [a] -> [a] -> [a]
++ [(Id
fn', Expr Id
rhs')]
combined_uds :: UsageDetails
combined_uds = UsageDetails
body_uds1 UsageDetails -> UsageDetails -> UsageDetails
`plusUDs` UsageDetails
rhs_uds
(free_uds :: UsageDetails
free_uds, dump_dbs :: Bag DictBind
dump_dbs, float_all :: Bool
float_all) = [Id] -> UsageDetails -> (UsageDetails, Bag DictBind, Bool)
dumpBindUDs [Id
fn] UsageDetails
combined_uds
final_binds :: [DictBind]
final_binds :: [DictBind]
final_binds
| Bool -> Bool
not (Bag DictBind -> Bool
forall a. Bag a -> Bool
isEmptyBag Bag DictBind
dump_dbs)
, Bool -> Bool
not ([(Id, Expr Id)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Id, Expr Id)]
spec_defns)
= [[(Id, Expr Id)] -> Bag DictBind -> DictBind
recWithDumpedDicts [(Id, Expr Id)]
pairs Bag DictBind
dump_dbs]
| Bool
otherwise
= [Bind Id -> DictBind
mkDB (Bind Id -> DictBind) -> Bind Id -> DictBind
forall a b. (a -> b) -> a -> b
$ Id -> Expr Id -> Bind Id
forall b. b -> Expr b -> Bind b
NonRec Id
b Expr Id
r | (b :: Id
b,r :: Expr Id
r) <- [(Id, Expr Id)]
pairs]
[DictBind] -> [DictBind] -> [DictBind]
forall a. [a] -> [a] -> [a]
++ Bag DictBind -> [DictBind]
forall a. Bag a -> [a]
bagToList Bag DictBind
dump_dbs
; if Bool
float_all then
(CoreProgram, UsageDetails) -> SpecM (CoreProgram, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], UsageDetails
free_uds UsageDetails -> [DictBind] -> UsageDetails
`snocDictBinds` [DictBind]
final_binds)
else
(CoreProgram, UsageDetails) -> SpecM (CoreProgram, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ((DictBind -> Bind Id) -> [DictBind] -> CoreProgram
forall a b. (a -> b) -> [a] -> [b]
map DictBind -> Bind Id
forall a b. (a, b) -> a
fst [DictBind]
final_binds, UsageDetails
free_uds) }
specBind rhs_env :: SpecEnv
rhs_env (Rec pairs :: [(Id, Expr Id)]
pairs) body_uds :: UsageDetails
body_uds
= do { let (bndrs :: [Id]
bndrs,rhss :: [Expr Id]
rhss) = [(Id, Expr Id)] -> ([Id], [Expr Id])
forall a b. [(a, b)] -> ([a], [b])
unzip [(Id, Expr Id)]
pairs
; (rhss' :: [Expr Id]
rhss', rhs_uds :: UsageDetails
rhs_uds) <- (Expr Id -> SpecM (Expr Id, UsageDetails))
-> [Expr Id] -> SpecM ([Expr Id], UsageDetails)
forall a b.
(a -> SpecM (b, UsageDetails)) -> [a] -> SpecM ([b], UsageDetails)
mapAndCombineSM (SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
rhs_env) [Expr Id]
rhss
; let scope_uds :: UsageDetails
scope_uds = UsageDetails
body_uds UsageDetails -> UsageDetails -> UsageDetails
`plusUDs` UsageDetails
rhs_uds
; (bndrs1 :: [Id]
bndrs1, spec_defns1 :: [(Id, Expr Id)]
spec_defns1, uds1 :: UsageDetails
uds1) <- SpecEnv
-> UsageDetails
-> [(Id, Expr Id)]
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
specDefns SpecEnv
rhs_env UsageDetails
scope_uds [(Id, Expr Id)]
pairs
; (bndrs3 :: [Id]
bndrs3, spec_defns3 :: [(Id, Expr Id)]
spec_defns3, uds3 :: UsageDetails
uds3)
<- if [(Id, Expr Id)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [(Id, Expr Id)]
spec_defns1
then ([Id], [(Id, Expr Id)], UsageDetails)
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Id]
bndrs1, [], UsageDetails
uds1)
else do {
(bndrs2 :: [Id]
bndrs2, spec_defns2 :: [(Id, Expr Id)]
spec_defns2, uds2 :: UsageDetails
uds2)
<- SpecEnv
-> UsageDetails
-> [(Id, Expr Id)]
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
specDefns SpecEnv
rhs_env UsageDetails
uds1 ([Id]
bndrs1 [Id] -> [Expr Id] -> [(Id, Expr Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Expr Id]
rhss)
; ([Id], [(Id, Expr Id)], UsageDetails)
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([Id]
bndrs2, [(Id, Expr Id)]
spec_defns2 [(Id, Expr Id)] -> [(Id, Expr Id)] -> [(Id, Expr Id)]
forall a. [a] -> [a] -> [a]
++ [(Id, Expr Id)]
spec_defns1, UsageDetails
uds2) }
; let (final_uds :: UsageDetails
final_uds, dumped_dbs :: Bag DictBind
dumped_dbs, float_all :: Bool
float_all) = [Id] -> UsageDetails -> (UsageDetails, Bag DictBind, Bool)
dumpBindUDs [Id]
bndrs UsageDetails
uds3
final_bind :: DictBind
final_bind = [(Id, Expr Id)] -> Bag DictBind -> DictBind
recWithDumpedDicts ([(Id, Expr Id)]
spec_defns3 [(Id, Expr Id)] -> [(Id, Expr Id)] -> [(Id, Expr Id)]
forall a. [a] -> [a] -> [a]
++ [Id] -> [Expr Id] -> [(Id, Expr Id)]
forall a b. [a] -> [b] -> [(a, b)]
zip [Id]
bndrs3 [Expr Id]
rhss')
Bag DictBind
dumped_dbs
; if Bool
float_all then
(CoreProgram, UsageDetails) -> SpecM (CoreProgram, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], UsageDetails
final_uds UsageDetails -> DictBind -> UsageDetails
`snocDictBind` DictBind
final_bind)
else
(CoreProgram, UsageDetails) -> SpecM (CoreProgram, UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([DictBind -> Bind Id
forall a b. (a, b) -> a
fst DictBind
final_bind], UsageDetails
final_uds) }
specDefns :: SpecEnv
-> UsageDetails
-> [(OutId,InExpr)]
-> SpecM ([OutId],
[(OutId,OutExpr)],
UsageDetails)
specDefns :: SpecEnv
-> UsageDetails
-> [(Id, Expr Id)]
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
specDefns _env :: SpecEnv
_env uds :: UsageDetails
uds []
= ([Id], [(Id, Expr Id)], UsageDetails)
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [], UsageDetails
uds)
specDefns env :: SpecEnv
env uds :: UsageDetails
uds ((bndr :: Id
bndr,rhs :: Expr Id
rhs):pairs :: [(Id, Expr Id)]
pairs)
= do { (bndrs1 :: [Id]
bndrs1, spec_defns1 :: [(Id, Expr Id)]
spec_defns1, uds1 :: UsageDetails
uds1) <- SpecEnv
-> UsageDetails
-> [(Id, Expr Id)]
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
specDefns SpecEnv
env UsageDetails
uds [(Id, Expr Id)]
pairs
; (bndr1 :: Id
bndr1, spec_defns2 :: [(Id, Expr Id)]
spec_defns2, uds2 :: UsageDetails
uds2) <- SpecEnv
-> UsageDetails
-> Id
-> Expr Id
-> SpecM (Id, [(Id, Expr Id)], UsageDetails)
specDefn SpecEnv
env UsageDetails
uds1 Id
bndr Expr Id
rhs
; ([Id], [(Id, Expr Id)], UsageDetails)
-> SpecM ([Id], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (Id
bndr1 Id -> [Id] -> [Id]
forall a. a -> [a] -> [a]
: [Id]
bndrs1, [(Id, Expr Id)]
spec_defns1 [(Id, Expr Id)] -> [(Id, Expr Id)] -> [(Id, Expr Id)]
forall a. [a] -> [a] -> [a]
++ [(Id, Expr Id)]
spec_defns2, UsageDetails
uds2) }
specDefn :: SpecEnv
-> UsageDetails
-> OutId -> InExpr
-> SpecM (Id,
[(Id,CoreExpr)],
UsageDetails)
specDefn :: SpecEnv
-> UsageDetails
-> Id
-> Expr Id
-> SpecM (Id, [(Id, Expr Id)], UsageDetails)
specDefn env :: SpecEnv
env body_uds :: UsageDetails
body_uds fn :: Id
fn rhs :: Expr Id
rhs
= do { let (body_uds_without_me :: UsageDetails
body_uds_without_me, calls_for_me :: [CallInfo]
calls_for_me) = Id -> UsageDetails -> (UsageDetails, [CallInfo])
callsForMe Id
fn UsageDetails
body_uds
rules_for_me :: [CoreRule]
rules_for_me = Id -> [CoreRule]
idCoreRules Id
fn
; (rules :: [CoreRule]
rules, spec_defns :: [(Id, Expr Id)]
spec_defns, spec_uds :: UsageDetails
spec_uds) <- Maybe Module
-> SpecEnv
-> [CoreRule]
-> [CallInfo]
-> Id
-> Expr Id
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
specCalls Maybe Module
forall a. Maybe a
Nothing SpecEnv
env [CoreRule]
rules_for_me
[CallInfo]
calls_for_me Id
fn Expr Id
rhs
; (Id, [(Id, Expr Id)], UsageDetails)
-> SpecM (Id, [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ( Id
fn Id -> [CoreRule] -> Id
`addIdSpecialisations` [CoreRule]
rules
, [(Id, Expr Id)]
spec_defns
, UsageDetails
body_uds_without_me UsageDetails -> UsageDetails -> UsageDetails
`plusUDs` UsageDetails
spec_uds) }
specCalls :: Maybe Module
-> SpecEnv
-> [CoreRule]
-> [CallInfo]
-> OutId -> InExpr
-> SpecM SpecInfo
type SpecInfo = ( [CoreRule]
, [(Id,CoreExpr)]
, UsageDetails )
specCalls :: Maybe Module
-> SpecEnv
-> [CoreRule]
-> [CallInfo]
-> Id
-> Expr Id
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
specCalls mb_mod :: Maybe Module
mb_mod env :: SpecEnv
env existing_rules :: [CoreRule]
existing_rules calls_for_me :: [CallInfo]
calls_for_me fn :: Id
fn rhs :: Expr Id
rhs
| [Id]
rhs_tyvars [Id] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
n_tyvars
Bool -> Bool -> Bool
&& [Id]
rhs_bndrs1 [Id] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthAtLeast` Int
n_dicts
Bool -> Bool -> Bool
&& [CallInfo] -> Bool
forall a. [a] -> Bool
notNull [CallInfo]
calls_for_me
Bool -> Bool -> Bool
&& Bool -> Bool
not (Activation -> Bool
isNeverActive (Id -> Activation
idInlineActivation Id
fn))
=
(([CoreRule], [(Id, Expr Id)], UsageDetails)
-> CallInfo -> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails))
-> ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> [CallInfo]
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a b.
Monad m =>
(a -> b -> m a) -> a -> [b] -> m a
foldlM ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> CallInfo -> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
spec_call ([], [], UsageDetails
emptyUDs) [CallInfo]
calls_for_me
| Bool
otherwise
= WARN( not (exprIsTrivial rhs) && notNull calls_for_me,
text "Missed specialisation opportunity for"
<+> ppr fn $$ _trace_doc )
([CoreRule], [(Id, Expr Id)], UsageDetails)
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], [], UsageDetails
emptyUDs)
where
_trace_doc :: SDoc
_trace_doc = [SDoc] -> SDoc
sep [ [Id] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Id]
rhs_tyvars, Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
n_tyvars
, [Id] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Id]
rhs_bndrs, Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
n_dicts
, Activation -> SDoc
forall a. Outputable a => a -> SDoc
ppr (Id -> Activation
idInlineActivation Id
fn) ]
fn_type :: Type
fn_type = Id -> Type
idType Id
fn
fn_arity :: Int
fn_arity = Id -> Int
idArity Id
fn
fn_unf :: Unfolding
fn_unf = Id -> Unfolding
realIdUnfolding Id
fn
(tyvars :: [Id]
tyvars, theta :: ThetaType
theta, _) = Type -> ([Id], ThetaType, Type)
tcSplitSigmaTy Type
fn_type
n_tyvars :: Int
n_tyvars = [Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
tyvars
n_dicts :: Int
n_dicts = ThetaType -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ThetaType
theta
inl_prag :: InlinePragma
inl_prag = Id -> InlinePragma
idInlinePragma Id
fn
inl_act :: Activation
inl_act = InlinePragma -> Activation
inlinePragmaActivation InlinePragma
inl_prag
is_local :: Bool
is_local = Id -> Bool
isLocalId Id
fn
(rhs_bndrs :: [Id]
rhs_bndrs, rhs_body :: Expr Id
rhs_body) = Expr Id -> ([Id], Expr Id)
collectBindersPushingCo Expr Id
rhs
(rhs_tyvars :: [Id]
rhs_tyvars, rhs_bndrs1 :: [Id]
rhs_bndrs1) = (Id -> Bool) -> [Id] -> ([Id], [Id])
forall a. (a -> Bool) -> [a] -> ([a], [a])
span Id -> Bool
isTyVar [Id]
rhs_bndrs
(rhs_dict_ids :: [Id]
rhs_dict_ids, rhs_bndrs2 :: [Id]
rhs_bndrs2) = Int -> [Id] -> ([Id], [Id])
forall a. Int -> [a] -> ([a], [a])
splitAt Int
n_dicts [Id]
rhs_bndrs1
body :: Expr Id
body = [Id] -> Expr Id -> Expr Id
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
rhs_bndrs2 Expr Id
rhs_body
in_scope :: InScopeSet
in_scope = Subst -> InScopeSet
CoreSubst.substInScope (SpecEnv -> Subst
se_subst SpecEnv
env)
already_covered :: DynFlags -> [CoreRule] -> [CoreExpr] -> Bool
already_covered :: DynFlags -> [CoreRule] -> [Expr Id] -> Bool
already_covered dflags :: DynFlags
dflags new_rules :: [CoreRule]
new_rules args :: [Expr Id]
args
= Maybe (CoreRule, Expr Id) -> Bool
forall a. Maybe a -> Bool
isJust (DynFlags
-> InScopeEnv
-> (Activation -> Bool)
-> Id
-> [Expr Id]
-> [CoreRule]
-> Maybe (CoreRule, Expr Id)
lookupRule DynFlags
dflags (InScopeSet
in_scope, Id -> Unfolding
realIdUnfolding)
(Bool -> Activation -> Bool
forall a b. a -> b -> a
const Bool
True) Id
fn [Expr Id]
args
([CoreRule]
new_rules [CoreRule] -> [CoreRule] -> [CoreRule]
forall a. [a] -> [a] -> [a]
++ [CoreRule]
existing_rules))
mk_ty_args :: [Maybe Type] -> [TyVar] -> [CoreExpr]
mk_ty_args :: [Maybe Type] -> [Id] -> [Expr Id]
mk_ty_args [] poly_tvs :: [Id]
poly_tvs
= ASSERT( null poly_tvs ) []
mk_ty_args (Nothing : call_ts :: [Maybe Type]
call_ts) (poly_tv :: Id
poly_tv : poly_tvs :: [Id]
poly_tvs)
= Type -> Expr Id
forall b. Type -> Expr b
Type (Id -> Type
mkTyVarTy Id
poly_tv) Expr Id -> [Expr Id] -> [Expr Id]
forall a. a -> [a] -> [a]
: [Maybe Type] -> [Id] -> [Expr Id]
mk_ty_args [Maybe Type]
call_ts [Id]
poly_tvs
mk_ty_args (Just ty :: Type
ty : call_ts :: [Maybe Type]
call_ts) poly_tvs :: [Id]
poly_tvs
= Type -> Expr Id
forall b. Type -> Expr b
Type Type
ty Expr Id -> [Expr Id] -> [Expr Id]
forall a. a -> [a] -> [a]
: [Maybe Type] -> [Id] -> [Expr Id]
mk_ty_args [Maybe Type]
call_ts [Id]
poly_tvs
mk_ty_args (Nothing : _) [] = String -> [Expr Id]
forall a. String -> a
panic "mk_ty_args"
spec_call :: SpecInfo
-> CallInfo
-> SpecM SpecInfo
spec_call :: ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> CallInfo -> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
spec_call spec_acc :: ([CoreRule], [(Id, Expr Id)], UsageDetails)
spec_acc@(rules_acc :: [CoreRule]
rules_acc, pairs_acc :: [(Id, Expr Id)]
pairs_acc, uds_acc :: UsageDetails
uds_acc)
(CI { ci_key :: CallInfo -> CallKey
ci_key = CallKey call_ts :: [Maybe Type]
call_ts, ci_args :: CallInfo -> [Expr Id]
ci_args = [Expr Id]
call_ds })
= ASSERT( call_ts `lengthIs` n_tyvars && call_ds `lengthIs` n_dicts )
do { let
spec_tv_binds :: [(Id, Type)]
spec_tv_binds = [(Id
tv,Type
ty) | (tv :: Id
tv, Just ty :: Type
ty) <- [Id]
rhs_tyvars [Id] -> [Maybe Type] -> [(Id, Maybe Type)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Maybe Type]
call_ts]
env1 :: SpecEnv
env1 = SpecEnv -> [(Id, Type)] -> SpecEnv
extendTvSubstList SpecEnv
env [(Id, Type)]
spec_tv_binds
(rhs_env :: SpecEnv
rhs_env, poly_tyvars :: [Id]
poly_tyvars) = SpecEnv -> [Id] -> (SpecEnv, [Id])
substBndrs SpecEnv
env1
[Id
tv | (tv :: Id
tv, Nothing) <- [Id]
rhs_tyvars [Id] -> [Maybe Type] -> [(Id, Maybe Type)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Maybe Type]
call_ts]
; [Id]
inst_dict_ids <- (Id -> SpecM Id) -> [Id] -> SpecM [Id]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
mapM (SpecEnv -> Id -> SpecM Id
newDictBndr SpecEnv
rhs_env) [Id]
rhs_dict_ids
; let (rhs_env2 :: SpecEnv
rhs_env2, dx_binds :: [DictBind]
dx_binds, spec_dict_args :: [Expr Id]
spec_dict_args)
= SpecEnv
-> [Id] -> [Expr Id] -> [Id] -> (SpecEnv, [DictBind], [Expr Id])
bindAuxiliaryDicts SpecEnv
rhs_env [Id]
rhs_dict_ids [Expr Id]
call_ds [Id]
inst_dict_ids
ty_args :: [Expr Id]
ty_args = [Maybe Type] -> [Id] -> [Expr Id]
mk_ty_args [Maybe Type]
call_ts [Id]
poly_tyvars
ev_args :: [Expr b]
ev_args = (Id -> Expr b) -> [Id] -> [Expr b]
forall a b. (a -> b) -> [a] -> [b]
map Id -> Expr b
forall b. Id -> Expr b
varToCoreExpr [Id]
inst_dict_ids
ev_bndrs :: [Id]
ev_bndrs = [Expr Id] -> [Id]
exprsFreeIdsList [Expr Id]
forall b. [Expr b]
ev_args
rule_args :: [Expr Id]
rule_args = [Expr Id]
ty_args [Expr Id] -> [Expr Id] -> [Expr Id]
forall a. [a] -> [a] -> [a]
++ [Expr Id]
forall b. [Expr b]
ev_args
rule_bndrs :: [Id]
rule_bndrs = [Id]
poly_tyvars [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id]
ev_bndrs
; DynFlags
dflags <- SpecM DynFlags
forall (m :: * -> *). HasDynFlags m => m DynFlags
getDynFlags
; if DynFlags -> [CoreRule] -> [Expr Id] -> Bool
already_covered DynFlags
dflags [CoreRule]
rules_acc [Expr Id]
rule_args
then ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([CoreRule], [(Id, Expr Id)], UsageDetails)
spec_acc
else
do
{
let body_ty :: Type
body_ty = Expr Id -> Type -> [Expr Id] -> Type
applyTypeToArgs Expr Id
rhs Type
fn_type [Expr Id]
rule_args
(lam_args :: [Id]
lam_args, app_args :: [Id]
app_args)
| HasDebugCallStack => Type -> Bool
Type -> Bool
isUnliftedType Type
body_ty
, Bool -> Bool
not (Id -> Bool
isJoinId Id
fn)
= ([Id]
poly_tyvars [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id
voidArgId], [Id]
poly_tyvars [Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
++ [Id
voidPrimId])
| Bool
otherwise = ([Id]
poly_tyvars, [Id]
poly_tyvars)
spec_id_ty :: Type
spec_id_ty = [Id] -> Type -> Type
mkLamTypes [Id]
lam_args Type
body_ty
join_arity_change :: Int
join_arity_change = [Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
app_args Int -> Int -> Int
forall a. Num a => a -> a -> a
- [Expr Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Expr Id]
rule_args
spec_join_arity :: Maybe Int
spec_join_arity | Just orig_join_arity :: Int
orig_join_arity <- Id -> Maybe Int
isJoinId_maybe Id
fn
= Int -> Maybe Int
forall a. a -> Maybe a
Just (Int
orig_join_arity Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
join_arity_change)
| Bool
otherwise
= Maybe Int
forall a. Maybe a
Nothing
; Id
spec_f <- Id -> Type -> Maybe Int -> SpecM Id
newSpecIdSM Id
fn Type
spec_id_ty Maybe Int
spec_join_arity
; (spec_rhs :: Expr Id
spec_rhs, rhs_uds :: UsageDetails
rhs_uds) <- SpecEnv -> Expr Id -> SpecM (Expr Id, UsageDetails)
specExpr SpecEnv
rhs_env2 ([Id] -> Expr Id -> Expr Id
forall b. [b] -> Expr b -> Expr b
mkLams [Id]
lam_args Expr Id
body)
; Module
this_mod <- SpecM Module
forall (m :: * -> *). HasModule m => m Module
getModule
; let
herald :: SDoc
herald = case Maybe Module
mb_mod of
Nothing
-> String -> SDoc
text "SPEC"
Just this_mod :: Module
this_mod
-> String -> SDoc
text "SPEC/" SDoc -> SDoc -> SDoc
<> Module -> SDoc
forall a. Outputable a => a -> SDoc
ppr Module
this_mod
rule_name :: FastString
rule_name = String -> FastString
mkFastString (String -> FastString) -> String -> FastString
forall a b. (a -> b) -> a -> b
$ DynFlags -> SDoc -> String
showSDoc DynFlags
dflags (SDoc -> String) -> SDoc -> String
forall a b. (a -> b) -> a -> b
$
SDoc
herald SDoc -> SDoc -> SDoc
<+> FastString -> SDoc
ftext (OccName -> FastString
occNameFS (Id -> OccName
forall a. NamedThing a => a -> OccName
getOccName Id
fn))
SDoc -> SDoc -> SDoc
<+> [SDoc] -> SDoc
hsep ((Maybe Type -> SDoc) -> [Maybe Type] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map Maybe Type -> SDoc
ppr_call_key_ty [Maybe Type]
call_ts)
rule_wout_eta :: CoreRule
rule_wout_eta = Module
-> Bool
-> Bool
-> FastString
-> Activation
-> Name
-> [Id]
-> [Expr Id]
-> Expr Id
-> CoreRule
mkRule
Module
this_mod
Bool
True
Bool
is_local
FastString
rule_name
Activation
inl_act
(Id -> Name
idName Id
fn)
[Id]
rule_bndrs
[Expr Id]
rule_args
(Expr Id -> [Id] -> Expr Id
forall b. Expr b -> [Id] -> Expr b
mkVarApps (Id -> Expr Id
forall b. Id -> Expr b
Var Id
spec_f) [Id]
app_args)
spec_rule :: CoreRule
spec_rule
= case Id -> Maybe Int
isJoinId_maybe Id
fn of
Just join_arity :: Int
join_arity -> Int -> CoreRule -> CoreRule
etaExpandToJoinPointRule Int
join_arity
CoreRule
rule_wout_eta
Nothing -> CoreRule
rule_wout_eta
spec_uds :: UsageDetails
spec_uds = (DictBind -> UsageDetails -> UsageDetails)
-> UsageDetails -> [DictBind] -> UsageDetails
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr DictBind -> UsageDetails -> UsageDetails
consDictBind UsageDetails
rhs_uds [DictBind]
dx_binds
(spec_inl_prag :: InlinePragma
spec_inl_prag, spec_unf :: Unfolding
spec_unf)
| Bool -> Bool
not Bool
is_local Bool -> Bool -> Bool
&& OccInfo -> Bool
isStrongLoopBreaker (Id -> OccInfo
idOccInfo Id
fn)
= (InlinePragma
neverInlinePragma, Unfolding
noUnfolding)
| InlinePragma { inl_inline :: InlinePragma -> InlineSpec
inl_inline = InlineSpec
Inlinable } <- InlinePragma
inl_prag
= (InlinePragma
inl_prag { inl_inline :: InlineSpec
inl_inline = InlineSpec
NoUserInline }, Unfolding
noUnfolding)
| Bool
otherwise
= (InlinePragma
inl_prag, DynFlags
-> [Id] -> (Expr Id -> Expr Id) -> Int -> Unfolding -> Unfolding
specUnfolding DynFlags
dflags [Id]
poly_tyvars Expr Id -> Expr Id
spec_app
Int
arity_decrease Unfolding
fn_unf)
arity_decrease :: Int
arity_decrease = [Expr Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Expr Id]
spec_dict_args
spec_app :: Expr Id -> Expr Id
spec_app e :: Expr Id
e = (Expr Id
e Expr Id -> [Expr Id] -> Expr Id
forall b. Expr b -> [Expr b] -> Expr b
`mkApps` [Expr Id]
ty_args) Expr Id -> [Expr Id] -> Expr Id
forall b. Expr b -> [Expr b] -> Expr b
`mkApps` [Expr Id]
spec_dict_args
spec_f_w_arity :: Id
spec_f_w_arity = Id
spec_f Id -> Int -> Id
`setIdArity` Int -> Int -> Int
forall a. Ord a => a -> a -> a
max 0 (Int
fn_arity Int -> Int -> Int
forall a. Num a => a -> a -> a
- Int
n_dicts)
Id -> InlinePragma -> Id
`setInlinePragma` InlinePragma
spec_inl_prag
Id -> Unfolding -> Id
`setIdUnfolding` Unfolding
spec_unf
Id -> Maybe Int -> Id
`asJoinId_maybe` Maybe Int
spec_join_arity
; ([CoreRule], [(Id, Expr Id)], UsageDetails)
-> SpecM ([CoreRule], [(Id, Expr Id)], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ( CoreRule
spec_rule CoreRule -> [CoreRule] -> [CoreRule]
forall a. a -> [a] -> [a]
: [CoreRule]
rules_acc
, (Id
spec_f_w_arity, Expr Id
spec_rhs) (Id, Expr Id) -> [(Id, Expr Id)] -> [(Id, Expr Id)]
forall a. a -> [a] -> [a]
: [(Id, Expr Id)]
pairs_acc
, UsageDetails
spec_uds UsageDetails -> UsageDetails -> UsageDetails
`plusUDs` UsageDetails
uds_acc
) } }
bindAuxiliaryDicts
:: SpecEnv
-> [DictId] -> [CoreExpr]
-> [DictId]
-> (SpecEnv,
[DictBind],
[CoreExpr])
bindAuxiliaryDicts :: SpecEnv
-> [Id] -> [Expr Id] -> [Id] -> (SpecEnv, [DictBind], [Expr Id])
bindAuxiliaryDicts env :: SpecEnv
env@(SE { se_subst :: SpecEnv -> Subst
se_subst = Subst
subst, se_interesting :: SpecEnv -> VarSet
se_interesting = VarSet
interesting })
orig_dict_ids :: [Id]
orig_dict_ids call_ds :: [Expr Id]
call_ds inst_dict_ids :: [Id]
inst_dict_ids
= (SpecEnv
env', [DictBind]
dx_binds, [Expr Id]
spec_dict_args)
where
(dx_binds :: [DictBind]
dx_binds, spec_dict_args :: [Expr Id]
spec_dict_args) = [Expr Id] -> [Id] -> ([DictBind], [Expr Id])
go [Expr Id]
call_ds [Id]
inst_dict_ids
env' :: SpecEnv
env' = SpecEnv
env { se_subst :: Subst
se_subst = Subst
subst Subst -> [(Id, Expr Id)] -> Subst
`CoreSubst.extendSubstList`
([Id]
orig_dict_ids [Id] -> [Expr Id] -> [(Id, Expr Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` [Expr Id]
spec_dict_args)
Subst -> [Id] -> Subst
`CoreSubst.extendInScopeList` [Id]
dx_ids
, se_interesting :: VarSet
se_interesting = VarSet
interesting VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
interesting_dicts }
dx_ids :: [Id]
dx_ids = [Id
dx_id | (NonRec dx_id :: Id
dx_id _, _) <- [DictBind]
dx_binds]
interesting_dicts :: VarSet
interesting_dicts = [Id] -> VarSet
mkVarSet [ Id
dx_id | (NonRec dx_id :: Id
dx_id dx :: Expr Id
dx, _) <- [DictBind]
dx_binds
, SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
dx ]
go :: [CoreExpr] -> [CoreBndr] -> ([DictBind], [CoreExpr])
go :: [Expr Id] -> [Id] -> ([DictBind], [Expr Id])
go [] _ = ([], [])
go (dx :: Expr Id
dx:dxs :: [Expr Id]
dxs) (dx_id :: Id
dx_id:dx_ids :: [Id]
dx_ids)
| Expr Id -> Bool
exprIsTrivial Expr Id
dx = ([DictBind]
dx_binds, Expr Id
dx Expr Id -> [Expr Id] -> [Expr Id]
forall a. a -> [a] -> [a]
: [Expr Id]
args)
| Bool
otherwise = (Bind Id -> DictBind
mkDB (Id -> Expr Id -> Bind Id
forall b. b -> Expr b -> Bind b
NonRec Id
dx_id Expr Id
dx) DictBind -> [DictBind] -> [DictBind]
forall a. a -> [a] -> [a]
: [DictBind]
dx_binds, Id -> Expr Id
forall b. Id -> Expr b
Var Id
dx_id Expr Id -> [Expr Id] -> [Expr Id]
forall a. a -> [a] -> [a]
: [Expr Id]
args)
where
(dx_binds :: [DictBind]
dx_binds, args :: [Expr Id]
args) = [Expr Id] -> [Id] -> ([DictBind], [Expr Id])
go [Expr Id]
dxs [Id]
dx_ids
go _ _ = String -> SDoc -> ([DictBind], [Expr Id])
forall a. HasCallStack => String -> SDoc -> a
pprPanic "bindAuxiliaryDicts" ([Id] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Id]
orig_dict_ids SDoc -> SDoc -> SDoc
$$ [Expr Id] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Expr Id]
call_ds SDoc -> SDoc -> SDoc
$$ [Id] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Id]
inst_dict_ids)
data UsageDetails
= MkUD {
UsageDetails -> Bag DictBind
ud_binds :: !(Bag DictBind),
UsageDetails -> CallDetails
ud_calls :: !CallDetails
}
type DictBind = (CoreBind, VarSet)
instance Outputable UsageDetails where
ppr :: UsageDetails -> SDoc
ppr (MkUD { ud_binds :: UsageDetails -> Bag DictBind
ud_binds = Bag DictBind
dbs, ud_calls :: UsageDetails -> CallDetails
ud_calls = CallDetails
calls })
= String -> SDoc
text "MkUD" SDoc -> SDoc -> SDoc
<+> SDoc -> SDoc
braces ([SDoc] -> SDoc
sep (SDoc -> [SDoc] -> [SDoc]
punctuate SDoc
comma
[String -> SDoc
text "binds" SDoc -> SDoc -> SDoc
<+> SDoc
equals SDoc -> SDoc -> SDoc
<+> Bag DictBind -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bag DictBind
dbs,
String -> SDoc
text "calls" SDoc -> SDoc -> SDoc
<+> SDoc
equals SDoc -> SDoc -> SDoc
<+> CallDetails -> SDoc
forall a. Outputable a => a -> SDoc
ppr CallDetails
calls]))
emptyUDs :: UsageDetails
emptyUDs :: UsageDetails
emptyUDs = $WMkUD :: Bag DictBind -> CallDetails -> UsageDetails
MkUD { ud_binds :: Bag DictBind
ud_binds = Bag DictBind
forall a. Bag a
emptyBag, ud_calls :: CallDetails
ud_calls = CallDetails
forall a. DVarEnv a
emptyDVarEnv }
type CallDetails = DIdEnv CallInfoSet
data CallInfoSet = CIS Id (Bag CallInfo)
data CallInfo
= CI { CallInfo -> CallKey
ci_key :: CallKey
, CallInfo -> [Expr Id]
ci_args :: [DictExpr]
, CallInfo -> VarSet
ci_fvs :: VarSet
}
newtype CallKey = CallKey [Maybe Type]
type DictExpr = CoreExpr
ciSetFilter :: (CallInfo -> Bool) -> CallInfoSet -> CallInfoSet
ciSetFilter :: (CallInfo -> Bool) -> CallInfoSet -> CallInfoSet
ciSetFilter p :: CallInfo -> Bool
p (CIS id :: Id
id a :: Bag CallInfo
a) = Id -> Bag CallInfo -> CallInfoSet
CIS Id
id ((CallInfo -> Bool) -> Bag CallInfo -> Bag CallInfo
forall a. (a -> Bool) -> Bag a -> Bag a
filterBag CallInfo -> Bool
p Bag CallInfo
a)
instance Outputable CallInfoSet where
ppr :: CallInfoSet -> SDoc
ppr (CIS fn :: Id
fn map :: Bag CallInfo
map) = SDoc -> Int -> SDoc -> SDoc
hang (String -> SDoc
text "CIS" SDoc -> SDoc -> SDoc
<+> Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
fn)
2 (Bag CallInfo -> SDoc
forall a. Outputable a => a -> SDoc
ppr Bag CallInfo
map)
pprCallInfo :: Id -> CallInfo -> SDoc
pprCallInfo :: Id -> CallInfo -> SDoc
pprCallInfo fn :: Id
fn (CI { ci_key :: CallInfo -> CallKey
ci_key = CallKey
key })
= Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
fn SDoc -> SDoc -> SDoc
<+> CallKey -> SDoc
forall a. Outputable a => a -> SDoc
ppr CallKey
key
ppr_call_key_ty :: Maybe Type -> SDoc
ppr_call_key_ty :: Maybe Type -> SDoc
ppr_call_key_ty Nothing = Char -> SDoc
char '_'
ppr_call_key_ty (Just ty :: Type
ty) = Char -> SDoc
char '@' SDoc -> SDoc -> SDoc
<+> Type -> SDoc
pprParendType Type
ty
instance Outputable CallKey where
ppr :: CallKey -> SDoc
ppr (CallKey ts :: [Maybe Type]
ts) = SDoc -> SDoc
brackets ([SDoc] -> SDoc
fsep ((Maybe Type -> SDoc) -> [Maybe Type] -> [SDoc]
forall a b. (a -> b) -> [a] -> [b]
map Maybe Type -> SDoc
ppr_call_key_ty [Maybe Type]
ts))
instance Outputable CallInfo where
ppr :: CallInfo -> SDoc
ppr (CI { ci_key :: CallInfo -> CallKey
ci_key = CallKey
key, ci_args :: CallInfo -> [Expr Id]
ci_args = [Expr Id]
args, ci_fvs :: CallInfo -> VarSet
ci_fvs = VarSet
fvs })
= String -> SDoc
text "CI" SDoc -> SDoc -> SDoc
<> SDoc -> SDoc
braces ([SDoc] -> SDoc
hsep [ CallKey -> SDoc
forall a. Outputable a => a -> SDoc
ppr CallKey
key, [Expr Id] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Expr Id]
args, VarSet -> SDoc
forall a. Outputable a => a -> SDoc
ppr VarSet
fvs ])
unionCalls :: CallDetails -> CallDetails -> CallDetails
unionCalls :: CallDetails -> CallDetails -> CallDetails
unionCalls c1 :: CallDetails
c1 c2 :: CallDetails
c2 = (CallInfoSet -> CallInfoSet -> CallInfoSet)
-> CallDetails -> CallDetails -> CallDetails
forall a. (a -> a -> a) -> DVarEnv a -> DVarEnv a -> DVarEnv a
plusDVarEnv_C CallInfoSet -> CallInfoSet -> CallInfoSet
unionCallInfoSet CallDetails
c1 CallDetails
c2
unionCallInfoSet :: CallInfoSet -> CallInfoSet -> CallInfoSet
unionCallInfoSet :: CallInfoSet -> CallInfoSet -> CallInfoSet
unionCallInfoSet (CIS f :: Id
f calls1 :: Bag CallInfo
calls1) (CIS _ calls2 :: Bag CallInfo
calls2) =
Id -> Bag CallInfo -> CallInfoSet
CIS Id
f (Bag CallInfo
calls1 Bag CallInfo -> Bag CallInfo -> Bag CallInfo
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag CallInfo
calls2)
callDetailsFVs :: CallDetails -> VarSet
callDetailsFVs :: CallDetails -> VarSet
callDetailsFVs calls :: CallDetails
calls =
(CallInfoSet -> VarSet -> VarSet)
-> VarSet -> CallDetails -> VarSet
forall elt a. (elt -> a -> a) -> a -> UniqDFM elt -> a
nonDetFoldUDFM (VarSet -> VarSet -> VarSet
unionVarSet (VarSet -> VarSet -> VarSet)
-> (CallInfoSet -> VarSet) -> CallInfoSet -> VarSet -> VarSet
forall b c a. (b -> c) -> (a -> b) -> a -> c
. CallInfoSet -> VarSet
callInfoFVs) VarSet
emptyVarSet CallDetails
calls
callInfoFVs :: CallInfoSet -> VarSet
callInfoFVs :: CallInfoSet -> VarSet
callInfoFVs (CIS _ call_info :: Bag CallInfo
call_info) =
(CallInfo -> VarSet -> VarSet) -> VarSet -> Bag CallInfo -> VarSet
forall a r. (a -> r -> r) -> r -> Bag a -> r
foldrBag (\(CI { ci_fvs :: CallInfo -> VarSet
ci_fvs = VarSet
fv }) vs :: VarSet
vs -> VarSet -> VarSet -> VarSet
unionVarSet VarSet
fv VarSet
vs) VarSet
emptyVarSet Bag CallInfo
call_info
singleCall :: Id -> [Maybe Type] -> [DictExpr] -> UsageDetails
singleCall :: Id -> [Maybe Type] -> [Expr Id] -> UsageDetails
singleCall id :: Id
id tys :: [Maybe Type]
tys dicts :: [Expr Id]
dicts
= $WMkUD :: Bag DictBind -> CallDetails -> UsageDetails
MkUD {ud_binds :: Bag DictBind
ud_binds = Bag DictBind
forall a. Bag a
emptyBag,
ud_calls :: CallDetails
ud_calls = Id -> CallInfoSet -> CallDetails
forall a. Id -> a -> DVarEnv a
unitDVarEnv Id
id (CallInfoSet -> CallDetails) -> CallInfoSet -> CallDetails
forall a b. (a -> b) -> a -> b
$ Id -> Bag CallInfo -> CallInfoSet
CIS Id
id (Bag CallInfo -> CallInfoSet) -> Bag CallInfo -> CallInfoSet
forall a b. (a -> b) -> a -> b
$
CallInfo -> Bag CallInfo
forall a. a -> Bag a
unitBag (CI :: CallKey -> [Expr Id] -> VarSet -> CallInfo
CI { ci_key :: CallKey
ci_key = [Maybe Type] -> CallKey
CallKey [Maybe Type]
tys
, ci_args :: [Expr Id]
ci_args = [Expr Id]
dicts
, ci_fvs :: VarSet
ci_fvs = VarSet
call_fvs }) }
where
call_fvs :: VarSet
call_fvs = [Expr Id] -> VarSet
exprsFreeVars [Expr Id]
dicts VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
tys_fvs
tys_fvs :: VarSet
tys_fvs = ThetaType -> VarSet
tyCoVarsOfTypes ([Maybe Type] -> ThetaType
forall a. [Maybe a] -> [a]
catMaybes [Maybe Type]
tys)
mkCallUDs, mkCallUDs' :: SpecEnv -> Id -> [CoreExpr] -> UsageDetails
mkCallUDs :: SpecEnv -> Id -> [Expr Id] -> UsageDetails
mkCallUDs env :: SpecEnv
env f :: Id
f args :: [Expr Id]
args
=
UsageDetails
res
where
res :: UsageDetails
res = SpecEnv -> Id -> [Expr Id] -> UsageDetails
mkCallUDs' SpecEnv
env Id
f [Expr Id]
args
mkCallUDs' :: SpecEnv -> Id -> [Expr Id] -> UsageDetails
mkCallUDs' env :: SpecEnv
env f :: Id
f args :: [Expr Id]
args
| Bool -> Bool
not (Id -> Bool
want_calls_for Id
f)
Bool -> Bool -> Bool
|| ThetaType -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ThetaType
theta
= UsageDetails
emptyUDs
| Bool -> Bool
not ((Type -> Bool) -> ThetaType -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
all Type -> Bool
type_determines_value ThetaType
theta)
Bool -> Bool -> Bool
|| Bool -> Bool
not ([Maybe Type]
spec_tys [Maybe Type] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
n_tyvars)
Bool -> Bool -> Bool
|| Bool -> Bool
not ( [Expr Id]
dicts [Expr Id] -> Int -> Bool
forall a. [a] -> Int -> Bool
`lengthIs` Int
n_dicts)
Bool -> Bool -> Bool
|| Bool -> Bool
not ((Expr Id -> Bool) -> [Expr Id] -> Bool
forall (t :: * -> *) a. Foldable t => (a -> Bool) -> t a -> Bool
any (SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env) [Expr Id]
dicts)
=
UsageDetails
emptyUDs
| Bool
otherwise
=
Id -> [Maybe Type] -> [Expr Id] -> UsageDetails
singleCall Id
f [Maybe Type]
spec_tys [Expr Id]
dicts
where
_trace_doc :: SDoc
_trace_doc = [SDoc] -> SDoc
vcat [Id -> SDoc
forall a. Outputable a => a -> SDoc
ppr Id
f, [Expr Id] -> SDoc
forall a. Outputable a => a -> SDoc
ppr [Expr Id]
args, Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
n_tyvars, Int -> SDoc
forall a. Outputable a => a -> SDoc
ppr Int
n_dicts
, [Bool] -> SDoc
forall a. Outputable a => a -> SDoc
ppr ((Expr Id -> Bool) -> [Expr Id] -> [Bool]
forall a b. (a -> b) -> [a] -> [b]
map (SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env) [Expr Id]
dicts)]
(tyvars :: [Id]
tyvars, theta :: ThetaType
theta, _) = Type -> ([Id], ThetaType, Type)
tcSplitSigmaTy (Id -> Type
idType Id
f)
constrained_tyvars :: VarSet
constrained_tyvars = ThetaType -> VarSet
tyCoVarsOfTypes ThetaType
theta
n_tyvars :: Int
n_tyvars = [Id] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Id]
tyvars
n_dicts :: Int
n_dicts = ThetaType -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length ThetaType
theta
spec_tys :: [Maybe Type]
spec_tys = [Id -> Type -> Maybe Type
forall a. Id -> a -> Maybe a
mk_spec_ty Id
tv Type
ty | (tv :: Id
tv, ty :: Type
ty) <- [Id]
tyvars [Id] -> [Expr Id] -> [(Id, Type)]
`type_zip` [Expr Id]
args]
dicts :: [Expr Id]
dicts = [Expr Id
dict_expr | (_, dict_expr :: Expr Id
dict_expr) <- ThetaType
theta ThetaType -> [Expr Id] -> [(Type, Expr Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` (Int -> [Expr Id] -> [Expr Id]
forall a. Int -> [a] -> [a]
drop Int
n_tyvars [Expr Id]
args)]
type_zip :: [TyVar] -> [CoreExpr] -> [(TyVar, Type)]
type_zip :: [Id] -> [Expr Id] -> [(Id, Type)]
type_zip tvs :: [Id]
tvs (Coercion _ : args :: [Expr Id]
args) = [Id] -> [Expr Id] -> [(Id, Type)]
type_zip [Id]
tvs [Expr Id]
args
type_zip (tv :: Id
tv:tvs :: [Id]
tvs) (Type ty :: Type
ty : args :: [Expr Id]
args) = (Id
tv, Type
ty) (Id, Type) -> [(Id, Type)] -> [(Id, Type)]
forall a. a -> [a] -> [a]
: [Id] -> [Expr Id] -> [(Id, Type)]
type_zip [Id]
tvs [Expr Id]
args
type_zip _ _ = []
mk_spec_ty :: Id -> a -> Maybe a
mk_spec_ty tyvar :: Id
tyvar ty :: a
ty
| Id
tyvar Id -> VarSet -> Bool
`elemVarSet` VarSet
constrained_tyvars = a -> Maybe a
forall a. a -> Maybe a
Just a
ty
| Bool
otherwise = Maybe a
forall a. Maybe a
Nothing
want_calls_for :: Id -> Bool
want_calls_for f :: Id
f = Id -> Bool
isLocalId Id
f Bool -> Bool -> Bool
|| Maybe (Expr Id) -> Bool
forall a. Maybe a -> Bool
isJust (Unfolding -> Maybe (Expr Id)
maybeUnfoldingTemplate (Id -> Unfolding
realIdUnfolding Id
f))
type_determines_value :: Type -> Bool
type_determines_value pred :: Type
pred
= case Type -> PredTree
classifyPredType Type
pred of
ClassPred cls :: Class
cls _ -> Bool -> Bool
not (Class -> Bool
isIPClass Class
cls)
EqPred {} -> Bool
True
IrredPred {} -> Bool
True
ForAllPred {} -> Bool
True
interestingDict :: SpecEnv -> CoreExpr -> Bool
interestingDict :: SpecEnv -> Expr Id -> Bool
interestingDict env :: SpecEnv
env (Var v :: Id
v) = Unfolding -> Bool
hasSomeUnfolding (Id -> Unfolding
idUnfolding Id
v)
Bool -> Bool -> Bool
|| Id -> Bool
isDataConWorkId Id
v
Bool -> Bool -> Bool
|| Id
v Id -> VarSet -> Bool
`elemVarSet` SpecEnv -> VarSet
se_interesting SpecEnv
env
interestingDict _ (Type _) = Bool
False
interestingDict _ (Coercion _) = Bool
False
interestingDict env :: SpecEnv
env (App fn :: Expr Id
fn (Type _)) = SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
fn
interestingDict env :: SpecEnv
env (App fn :: Expr Id
fn (Coercion _)) = SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
fn
interestingDict env :: SpecEnv
env (Tick _ a :: Expr Id
a) = SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
a
interestingDict env :: SpecEnv
env (Cast e :: Expr Id
e _) = SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
e
interestingDict _ _ = Bool
True
plusUDs :: UsageDetails -> UsageDetails -> UsageDetails
plusUDs :: UsageDetails -> UsageDetails -> UsageDetails
plusUDs (MkUD {ud_binds :: UsageDetails -> Bag DictBind
ud_binds = Bag DictBind
db1, ud_calls :: UsageDetails -> CallDetails
ud_calls = CallDetails
calls1})
(MkUD {ud_binds :: UsageDetails -> Bag DictBind
ud_binds = Bag DictBind
db2, ud_calls :: UsageDetails -> CallDetails
ud_calls = CallDetails
calls2})
= $WMkUD :: Bag DictBind -> CallDetails -> UsageDetails
MkUD { ud_binds :: Bag DictBind
ud_binds = Bag DictBind
db1 Bag DictBind -> Bag DictBind -> Bag DictBind
forall a. Bag a -> Bag a -> Bag a
`unionBags` Bag DictBind
db2
, ud_calls :: CallDetails
ud_calls = CallDetails
calls1 CallDetails -> CallDetails -> CallDetails
`unionCalls` CallDetails
calls2 }
_dictBindBndrs :: Bag DictBind -> [Id]
_dictBindBndrs :: Bag DictBind -> [Id]
_dictBindBndrs dbs :: Bag DictBind
dbs = (DictBind -> [Id] -> [Id]) -> [Id] -> Bag DictBind -> [Id]
forall a r. (a -> r -> r) -> r -> Bag a -> r
foldrBag ([Id] -> [Id] -> [Id]
forall a. [a] -> [a] -> [a]
(++) ([Id] -> [Id] -> [Id])
-> (DictBind -> [Id]) -> DictBind -> [Id] -> [Id]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Bind Id -> [Id]
forall b. Bind b -> [b]
bindersOf (Bind Id -> [Id]) -> (DictBind -> Bind Id) -> DictBind -> [Id]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. DictBind -> Bind Id
forall a b. (a, b) -> a
fst) [] Bag DictBind
dbs
mkDB :: CoreBind -> DictBind
mkDB :: Bind Id -> DictBind
mkDB bind :: Bind Id
bind = (Bind Id
bind, Bind Id -> VarSet
bind_fvs Bind Id
bind)
bind_fvs :: CoreBind -> VarSet
bind_fvs :: Bind Id -> VarSet
bind_fvs (NonRec bndr :: Id
bndr rhs :: Expr Id
rhs) = (Id, Expr Id) -> VarSet
pair_fvs (Id
bndr,Expr Id
rhs)
bind_fvs (Rec prs :: [(Id, Expr Id)]
prs) = (VarSet -> Id -> VarSet) -> VarSet -> [Id] -> VarSet
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' VarSet -> Id -> VarSet
delVarSet VarSet
rhs_fvs [Id]
bndrs
where
bndrs :: [Id]
bndrs = ((Id, Expr Id) -> Id) -> [(Id, Expr Id)] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map (Id, Expr Id) -> Id
forall a b. (a, b) -> a
fst [(Id, Expr Id)]
prs
rhs_fvs :: VarSet
rhs_fvs = [VarSet] -> VarSet
unionVarSets (((Id, Expr Id) -> VarSet) -> [(Id, Expr Id)] -> [VarSet]
forall a b. (a -> b) -> [a] -> [b]
map (Id, Expr Id) -> VarSet
pair_fvs [(Id, Expr Id)]
prs)
pair_fvs :: (Id, CoreExpr) -> VarSet
pair_fvs :: (Id, Expr Id) -> VarSet
pair_fvs (bndr :: Id
bndr, rhs :: Expr Id
rhs) = (Id -> Bool) -> Expr Id -> VarSet
exprSomeFreeVars Id -> Bool
interesting Expr Id
rhs
VarSet -> VarSet -> VarSet
`unionVarSet` Id -> VarSet
idFreeVars Id
bndr
where
interesting :: InterestingVarFun
interesting :: Id -> Bool
interesting v :: Id
v = Id -> Bool
isLocalVar Id
v Bool -> Bool -> Bool
|| (Id -> Bool
isId Id
v Bool -> Bool -> Bool
&& Id -> Bool
isDFunId Id
v)
recWithDumpedDicts :: [(Id,CoreExpr)] -> Bag DictBind ->DictBind
recWithDumpedDicts :: [(Id, Expr Id)] -> Bag DictBind -> DictBind
recWithDumpedDicts pairs :: [(Id, Expr Id)]
pairs dbs :: Bag DictBind
dbs
= ([(Id, Expr Id)] -> Bind Id
forall b. [(b, Expr b)] -> Bind b
Rec [(Id, Expr Id)]
bindings, VarSet
fvs)
where
(bindings :: [(Id, Expr Id)]
bindings, fvs :: VarSet
fvs) = (DictBind
-> ([(Id, Expr Id)], VarSet) -> ([(Id, Expr Id)], VarSet))
-> ([(Id, Expr Id)], VarSet)
-> Bag DictBind
-> ([(Id, Expr Id)], VarSet)
forall a r. (a -> r -> r) -> r -> Bag a -> r
foldrBag DictBind -> ([(Id, Expr Id)], VarSet) -> ([(Id, Expr Id)], VarSet)
forall a.
(Bind a, VarSet)
-> ([(a, Expr a)], VarSet) -> ([(a, Expr a)], VarSet)
add
([], VarSet
emptyVarSet)
(Bag DictBind
dbs Bag DictBind -> DictBind -> Bag DictBind
forall a. Bag a -> a -> Bag a
`snocBag` Bind Id -> DictBind
mkDB ([(Id, Expr Id)] -> Bind Id
forall b. [(b, Expr b)] -> Bind b
Rec [(Id, Expr Id)]
pairs))
add :: (Bind a, VarSet)
-> ([(a, Expr a)], VarSet) -> ([(a, Expr a)], VarSet)
add (NonRec b :: a
b r :: Expr a
r, fvs' :: VarSet
fvs') (pairs :: [(a, Expr a)]
pairs, fvs :: VarSet
fvs) =
((a
b,Expr a
r) (a, Expr a) -> [(a, Expr a)] -> [(a, Expr a)]
forall a. a -> [a] -> [a]
: [(a, Expr a)]
pairs, VarSet
fvs VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
fvs')
add (Rec prs1 :: [(a, Expr a)]
prs1, fvs' :: VarSet
fvs') (pairs :: [(a, Expr a)]
pairs, fvs :: VarSet
fvs) =
([(a, Expr a)]
prs1 [(a, Expr a)] -> [(a, Expr a)] -> [(a, Expr a)]
forall a. [a] -> [a] -> [a]
++ [(a, Expr a)]
pairs, VarSet
fvs VarSet -> VarSet -> VarSet
`unionVarSet` VarSet
fvs')
snocDictBinds :: UsageDetails -> [DictBind] -> UsageDetails
snocDictBinds :: UsageDetails -> [DictBind] -> UsageDetails
snocDictBinds uds :: UsageDetails
uds dbs :: [DictBind]
dbs
= UsageDetails
uds { ud_binds :: Bag DictBind
ud_binds = UsageDetails -> Bag DictBind
ud_binds UsageDetails
uds Bag DictBind -> Bag DictBind -> Bag DictBind
forall a. Bag a -> Bag a -> Bag a
`unionBags` [DictBind] -> Bag DictBind
forall a. [a] -> Bag a
listToBag [DictBind]
dbs }
consDictBind :: DictBind -> UsageDetails -> UsageDetails
consDictBind :: DictBind -> UsageDetails -> UsageDetails
consDictBind bind :: DictBind
bind uds :: UsageDetails
uds = UsageDetails
uds { ud_binds :: Bag DictBind
ud_binds = DictBind
bind DictBind -> Bag DictBind -> Bag DictBind
forall a. a -> Bag a -> Bag a
`consBag` UsageDetails -> Bag DictBind
ud_binds UsageDetails
uds }
addDictBinds :: [DictBind] -> UsageDetails -> UsageDetails
addDictBinds :: [DictBind] -> UsageDetails -> UsageDetails
addDictBinds binds :: [DictBind]
binds uds :: UsageDetails
uds = UsageDetails
uds { ud_binds :: Bag DictBind
ud_binds = [DictBind] -> Bag DictBind
forall a. [a] -> Bag a
listToBag [DictBind]
binds Bag DictBind -> Bag DictBind -> Bag DictBind
forall a. Bag a -> Bag a -> Bag a
`unionBags` UsageDetails -> Bag DictBind
ud_binds UsageDetails
uds }
snocDictBind :: UsageDetails -> DictBind -> UsageDetails
snocDictBind :: UsageDetails -> DictBind -> UsageDetails
snocDictBind uds :: UsageDetails
uds bind :: DictBind
bind = UsageDetails
uds { ud_binds :: Bag DictBind
ud_binds = UsageDetails -> Bag DictBind
ud_binds UsageDetails
uds Bag DictBind -> DictBind -> Bag DictBind
forall a. Bag a -> a -> Bag a
`snocBag` DictBind
bind }
wrapDictBinds :: Bag DictBind -> [CoreBind] -> [CoreBind]
wrapDictBinds :: Bag DictBind -> CoreProgram -> CoreProgram
wrapDictBinds dbs :: Bag DictBind
dbs binds :: CoreProgram
binds
= (DictBind -> CoreProgram -> CoreProgram)
-> CoreProgram -> Bag DictBind -> CoreProgram
forall a r. (a -> r -> r) -> r -> Bag a -> r
foldrBag DictBind -> CoreProgram -> CoreProgram
forall a b. (a, b) -> [a] -> [a]
add CoreProgram
binds Bag DictBind
dbs
where
add :: (a, b) -> [a] -> [a]
add (bind :: a
bind,_) binds :: [a]
binds = a
bind a -> [a] -> [a]
forall a. a -> [a] -> [a]
: [a]
binds
wrapDictBindsE :: Bag DictBind -> CoreExpr -> CoreExpr
wrapDictBindsE :: Bag DictBind -> Expr Id -> Expr Id
wrapDictBindsE dbs :: Bag DictBind
dbs expr :: Expr Id
expr
= (DictBind -> Expr Id -> Expr Id)
-> Expr Id -> Bag DictBind -> Expr Id
forall a r. (a -> r -> r) -> r -> Bag a -> r
foldrBag DictBind -> Expr Id -> Expr Id
forall b b. (Bind b, b) -> Expr b -> Expr b
add Expr Id
expr Bag DictBind
dbs
where
add :: (Bind b, b) -> Expr b -> Expr b
add (bind :: Bind b
bind,_) expr :: Expr b
expr = Bind b -> Expr b -> Expr b
forall b. Bind b -> Expr b -> Expr b
Let Bind b
bind Expr b
expr
dumpUDs :: [CoreBndr] -> UsageDetails -> (UsageDetails, Bag DictBind)
dumpUDs :: [Id] -> UsageDetails -> (UsageDetails, Bag DictBind)
dumpUDs bndrs :: [Id]
bndrs uds :: UsageDetails
uds@(MkUD { ud_binds :: UsageDetails -> Bag DictBind
ud_binds = Bag DictBind
orig_dbs, ud_calls :: UsageDetails -> CallDetails
ud_calls = CallDetails
orig_calls })
| [Id] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [Id]
bndrs = (UsageDetails
uds, Bag DictBind
forall a. Bag a
emptyBag)
| Bool
otherwise =
(UsageDetails
free_uds, Bag DictBind
dump_dbs)
where
free_uds :: UsageDetails
free_uds = $WMkUD :: Bag DictBind -> CallDetails -> UsageDetails
MkUD { ud_binds :: Bag DictBind
ud_binds = Bag DictBind
free_dbs, ud_calls :: CallDetails
ud_calls = CallDetails
free_calls }
bndr_set :: VarSet
bndr_set = [Id] -> VarSet
mkVarSet [Id]
bndrs
(free_dbs :: Bag DictBind
free_dbs, dump_dbs :: Bag DictBind
dump_dbs, dump_set :: VarSet
dump_set) = Bag DictBind -> VarSet -> (Bag DictBind, Bag DictBind, VarSet)
splitDictBinds Bag DictBind
orig_dbs VarSet
bndr_set
free_calls :: CallDetails
free_calls = VarSet -> CallDetails -> CallDetails
deleteCallsMentioning VarSet
dump_set (CallDetails -> CallDetails) -> CallDetails -> CallDetails
forall a b. (a -> b) -> a -> b
$
[Id] -> CallDetails -> CallDetails
deleteCallsFor [Id]
bndrs CallDetails
orig_calls
dumpBindUDs :: [CoreBndr] -> UsageDetails -> (UsageDetails, Bag DictBind, Bool)
dumpBindUDs :: [Id] -> UsageDetails -> (UsageDetails, Bag DictBind, Bool)
dumpBindUDs bndrs :: [Id]
bndrs (MkUD { ud_binds :: UsageDetails -> Bag DictBind
ud_binds = Bag DictBind
orig_dbs, ud_calls :: UsageDetails -> CallDetails
ud_calls = CallDetails
orig_calls })
=
(UsageDetails
free_uds, Bag DictBind
dump_dbs, Bool
float_all)
where
free_uds :: UsageDetails
free_uds = $WMkUD :: Bag DictBind -> CallDetails -> UsageDetails
MkUD { ud_binds :: Bag DictBind
ud_binds = Bag DictBind
free_dbs, ud_calls :: CallDetails
ud_calls = CallDetails
free_calls }
bndr_set :: VarSet
bndr_set = [Id] -> VarSet
mkVarSet [Id]
bndrs
(free_dbs :: Bag DictBind
free_dbs, dump_dbs :: Bag DictBind
dump_dbs, dump_set :: VarSet
dump_set) = Bag DictBind -> VarSet -> (Bag DictBind, Bag DictBind, VarSet)
splitDictBinds Bag DictBind
orig_dbs VarSet
bndr_set
free_calls :: CallDetails
free_calls = [Id] -> CallDetails -> CallDetails
deleteCallsFor [Id]
bndrs CallDetails
orig_calls
float_all :: Bool
float_all = VarSet
dump_set VarSet -> VarSet -> Bool
`intersectsVarSet` CallDetails -> VarSet
callDetailsFVs CallDetails
free_calls
callsForMe :: Id -> UsageDetails -> (UsageDetails, [CallInfo])
callsForMe :: Id -> UsageDetails -> (UsageDetails, [CallInfo])
callsForMe fn :: Id
fn (MkUD { ud_binds :: UsageDetails -> Bag DictBind
ud_binds = Bag DictBind
orig_dbs, ud_calls :: UsageDetails -> CallDetails
ud_calls = CallDetails
orig_calls })
=
(UsageDetails
uds_without_me, [CallInfo]
calls_for_me)
where
uds_without_me :: UsageDetails
uds_without_me = $WMkUD :: Bag DictBind -> CallDetails -> UsageDetails
MkUD { ud_binds :: Bag DictBind
ud_binds = Bag DictBind
orig_dbs
, ud_calls :: CallDetails
ud_calls = CallDetails -> Id -> CallDetails
forall a. DVarEnv a -> Id -> DVarEnv a
delDVarEnv CallDetails
orig_calls Id
fn }
calls_for_me :: [CallInfo]
calls_for_me = case CallDetails -> Id -> Maybe CallInfoSet
forall a. DVarEnv a -> Id -> Maybe a
lookupDVarEnv CallDetails
orig_calls Id
fn of
Nothing -> []
Just cis :: CallInfoSet
cis -> CallInfoSet -> Bag DictBind -> [CallInfo]
filterCalls CallInfoSet
cis Bag DictBind
orig_dbs
filterCalls :: CallInfoSet -> Bag DictBind -> [CallInfo]
filterCalls :: CallInfoSet -> Bag DictBind -> [CallInfo]
filterCalls (CIS fn :: Id
fn call_bag :: Bag CallInfo
call_bag) dbs :: Bag DictBind
dbs
= (CallInfo -> Bool) -> [CallInfo] -> [CallInfo]
forall a. (a -> Bool) -> [a] -> [a]
filter CallInfo -> Bool
ok_call (Bag CallInfo -> [CallInfo]
forall a. Bag a -> [a]
bagToList Bag CallInfo
call_bag)
where
dump_set :: VarSet
dump_set = (VarSet -> DictBind -> VarSet) -> VarSet -> Bag DictBind -> VarSet
forall r a. (r -> a -> r) -> r -> Bag a -> r
foldlBag VarSet -> DictBind -> VarSet
go (Id -> VarSet
unitVarSet Id
fn) Bag DictBind
dbs
go :: VarSet -> DictBind -> VarSet
go so_far :: VarSet
so_far (db :: Bind Id
db,fvs :: VarSet
fvs) | VarSet
fvs VarSet -> VarSet -> Bool
`intersectsVarSet` VarSet
so_far
= VarSet -> [Id] -> VarSet
extendVarSetList VarSet
so_far (Bind Id -> [Id]
forall b. Bind b -> [b]
bindersOf Bind Id
db)
| Bool
otherwise = VarSet
so_far
ok_call :: CallInfo -> Bool
ok_call (CI { ci_fvs :: CallInfo -> VarSet
ci_fvs = VarSet
fvs }) = Bool -> Bool
not (VarSet
fvs VarSet -> VarSet -> Bool
`intersectsVarSet` VarSet
dump_set)
splitDictBinds :: Bag DictBind -> IdSet -> (Bag DictBind, Bag DictBind, IdSet)
splitDictBinds :: Bag DictBind -> VarSet -> (Bag DictBind, Bag DictBind, VarSet)
splitDictBinds dbs :: Bag DictBind
dbs bndr_set :: VarSet
bndr_set
= ((Bag DictBind, Bag DictBind, VarSet)
-> DictBind -> (Bag DictBind, Bag DictBind, VarSet))
-> (Bag DictBind, Bag DictBind, VarSet)
-> Bag DictBind
-> (Bag DictBind, Bag DictBind, VarSet)
forall r a. (r -> a -> r) -> r -> Bag a -> r
foldlBag (Bag DictBind, Bag DictBind, VarSet)
-> DictBind -> (Bag DictBind, Bag DictBind, VarSet)
split_db (Bag DictBind
forall a. Bag a
emptyBag, Bag DictBind
forall a. Bag a
emptyBag, VarSet
bndr_set) Bag DictBind
dbs
where
split_db :: (Bag DictBind, Bag DictBind, VarSet)
-> DictBind -> (Bag DictBind, Bag DictBind, VarSet)
split_db (free_dbs :: Bag DictBind
free_dbs, dump_dbs :: Bag DictBind
dump_dbs, dump_idset :: VarSet
dump_idset) db :: DictBind
db@(bind :: Bind Id
bind, fvs :: VarSet
fvs)
| VarSet
dump_idset VarSet -> VarSet -> Bool
`intersectsVarSet` VarSet
fvs
= (Bag DictBind
free_dbs, Bag DictBind
dump_dbs Bag DictBind -> DictBind -> Bag DictBind
forall a. Bag a -> a -> Bag a
`snocBag` DictBind
db,
VarSet -> [Id] -> VarSet
extendVarSetList VarSet
dump_idset (Bind Id -> [Id]
forall b. Bind b -> [b]
bindersOf Bind Id
bind))
| Bool
otherwise
= (Bag DictBind
free_dbs Bag DictBind -> DictBind -> Bag DictBind
forall a. Bag a -> a -> Bag a
`snocBag` DictBind
db, Bag DictBind
dump_dbs, VarSet
dump_idset)
deleteCallsMentioning :: VarSet -> CallDetails -> CallDetails
deleteCallsMentioning :: VarSet -> CallDetails -> CallDetails
deleteCallsMentioning bs :: VarSet
bs calls :: CallDetails
calls
= (CallInfoSet -> CallInfoSet) -> CallDetails -> CallDetails
forall a b. (a -> b) -> DVarEnv a -> DVarEnv b
mapDVarEnv ((CallInfo -> Bool) -> CallInfoSet -> CallInfoSet
ciSetFilter CallInfo -> Bool
keep_call) CallDetails
calls
where
keep_call :: CallInfo -> Bool
keep_call (CI { ci_fvs :: CallInfo -> VarSet
ci_fvs = VarSet
fvs }) = Bool -> Bool
not (VarSet
fvs VarSet -> VarSet -> Bool
`intersectsVarSet` VarSet
bs)
deleteCallsFor :: [Id] -> CallDetails -> CallDetails
deleteCallsFor :: [Id] -> CallDetails -> CallDetails
deleteCallsFor bs :: [Id]
bs calls :: CallDetails
calls = CallDetails -> [Id] -> CallDetails
forall a. DVarEnv a -> [Id] -> DVarEnv a
delDVarEnvList CallDetails
calls [Id]
bs
newtype SpecM a = SpecM (State SpecState a)
data SpecState = SpecState {
SpecState -> UniqSupply
spec_uniq_supply :: UniqSupply,
SpecState -> Module
spec_module :: Module,
SpecState -> DynFlags
spec_dflags :: DynFlags
}
instance Functor SpecM where
fmap :: (a -> b) -> SpecM a -> SpecM b
fmap = (a -> b) -> SpecM a -> SpecM b
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM
instance Applicative SpecM where
pure :: a -> SpecM a
pure x :: a
x = State SpecState a -> SpecM a
forall a. State SpecState a -> SpecM a
SpecM (State SpecState a -> SpecM a) -> State SpecState a -> SpecM a
forall a b. (a -> b) -> a -> b
$ a -> State SpecState a
forall (m :: * -> *) a. Monad m => a -> m a
return a
x
<*> :: SpecM (a -> b) -> SpecM a -> SpecM b
(<*>) = SpecM (a -> b) -> SpecM a -> SpecM b
forall (m :: * -> *) a b. Monad m => m (a -> b) -> m a -> m b
ap
instance Monad SpecM where
SpecM x :: State SpecState a
x >>= :: SpecM a -> (a -> SpecM b) -> SpecM b
>>= f :: a -> SpecM b
f = State SpecState b -> SpecM b
forall a. State SpecState a -> SpecM a
SpecM (State SpecState b -> SpecM b) -> State SpecState b -> SpecM b
forall a b. (a -> b) -> a -> b
$ do a
y <- State SpecState a
x
case a -> SpecM b
f a
y of
SpecM z :: State SpecState b
z ->
State SpecState b
z
#if !MIN_VERSION_base(4,13,0)
fail = MonadFail.fail
#endif
instance MonadFail.MonadFail SpecM where
fail :: String -> SpecM a
fail str :: String
str = State SpecState a -> SpecM a
forall a. State SpecState a -> SpecM a
SpecM (State SpecState a -> SpecM a) -> State SpecState a -> SpecM a
forall a b. (a -> b) -> a -> b
$ String -> State SpecState a
forall a. HasCallStack => String -> a
error String
str
instance MonadUnique SpecM where
getUniqueSupplyM :: SpecM UniqSupply
getUniqueSupplyM
= State SpecState UniqSupply -> SpecM UniqSupply
forall a. State SpecState a -> SpecM a
SpecM (State SpecState UniqSupply -> SpecM UniqSupply)
-> State SpecState UniqSupply -> SpecM UniqSupply
forall a b. (a -> b) -> a -> b
$ do SpecState
st <- State SpecState SpecState
forall s. State s s
get
let (us1 :: UniqSupply
us1, us2 :: UniqSupply
us2) = UniqSupply -> (UniqSupply, UniqSupply)
splitUniqSupply (UniqSupply -> (UniqSupply, UniqSupply))
-> UniqSupply -> (UniqSupply, UniqSupply)
forall a b. (a -> b) -> a -> b
$ SpecState -> UniqSupply
spec_uniq_supply SpecState
st
SpecState -> State SpecState ()
forall s. s -> State s ()
put (SpecState -> State SpecState ())
-> SpecState -> State SpecState ()
forall a b. (a -> b) -> a -> b
$ SpecState
st { spec_uniq_supply :: UniqSupply
spec_uniq_supply = UniqSupply
us2 }
UniqSupply -> State SpecState UniqSupply
forall (m :: * -> *) a. Monad m => a -> m a
return UniqSupply
us1
getUniqueM :: SpecM Unique
getUniqueM
= State SpecState Unique -> SpecM Unique
forall a. State SpecState a -> SpecM a
SpecM (State SpecState Unique -> SpecM Unique)
-> State SpecState Unique -> SpecM Unique
forall a b. (a -> b) -> a -> b
$ do SpecState
st <- State SpecState SpecState
forall s. State s s
get
let (u :: Unique
u,us' :: UniqSupply
us') = UniqSupply -> (Unique, UniqSupply)
takeUniqFromSupply (UniqSupply -> (Unique, UniqSupply))
-> UniqSupply -> (Unique, UniqSupply)
forall a b. (a -> b) -> a -> b
$ SpecState -> UniqSupply
spec_uniq_supply SpecState
st
SpecState -> State SpecState ()
forall s. s -> State s ()
put (SpecState -> State SpecState ())
-> SpecState -> State SpecState ()
forall a b. (a -> b) -> a -> b
$ SpecState
st { spec_uniq_supply :: UniqSupply
spec_uniq_supply = UniqSupply
us' }
Unique -> State SpecState Unique
forall (m :: * -> *) a. Monad m => a -> m a
return Unique
u
instance HasDynFlags SpecM where
getDynFlags :: SpecM DynFlags
getDynFlags = State SpecState DynFlags -> SpecM DynFlags
forall a. State SpecState a -> SpecM a
SpecM (State SpecState DynFlags -> SpecM DynFlags)
-> State SpecState DynFlags -> SpecM DynFlags
forall a b. (a -> b) -> a -> b
$ (SpecState -> DynFlags)
-> State SpecState SpecState -> State SpecState DynFlags
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM SpecState -> DynFlags
spec_dflags State SpecState SpecState
forall s. State s s
get
instance HasModule SpecM where
getModule :: SpecM Module
getModule = State SpecState Module -> SpecM Module
forall a. State SpecState a -> SpecM a
SpecM (State SpecState Module -> SpecM Module)
-> State SpecState Module -> SpecM Module
forall a b. (a -> b) -> a -> b
$ (SpecState -> Module)
-> State SpecState SpecState -> State SpecState Module
forall (m :: * -> *) a1 r. Monad m => (a1 -> r) -> m a1 -> m r
liftM SpecState -> Module
spec_module State SpecState SpecState
forall s. State s s
get
runSpecM :: DynFlags -> Module -> SpecM a -> CoreM a
runSpecM :: DynFlags -> Module -> SpecM a -> CoreM a
runSpecM dflags :: DynFlags
dflags this_mod :: Module
this_mod (SpecM spec :: State SpecState a
spec)
= do UniqSupply
us <- CoreM UniqSupply
forall (m :: * -> *). MonadUnique m => m UniqSupply
getUniqueSupplyM
let initialState :: SpecState
initialState = SpecState :: UniqSupply -> Module -> DynFlags -> SpecState
SpecState {
spec_uniq_supply :: UniqSupply
spec_uniq_supply = UniqSupply
us,
spec_module :: Module
spec_module = Module
this_mod,
spec_dflags :: DynFlags
spec_dflags = DynFlags
dflags
}
a -> CoreM a
forall (m :: * -> *) a. Monad m => a -> m a
return (a -> CoreM a) -> a -> CoreM a
forall a b. (a -> b) -> a -> b
$ State SpecState a -> SpecState -> a
forall s a. State s a -> s -> a
evalState State SpecState a
spec SpecState
initialState
mapAndCombineSM :: (a -> SpecM (b, UsageDetails)) -> [a] -> SpecM ([b], UsageDetails)
mapAndCombineSM :: (a -> SpecM (b, UsageDetails)) -> [a] -> SpecM ([b], UsageDetails)
mapAndCombineSM _ [] = ([b], UsageDetails) -> SpecM ([b], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return ([], UsageDetails
emptyUDs)
mapAndCombineSM f :: a -> SpecM (b, UsageDetails)
f (x :: a
x:xs :: [a]
xs) = do (y :: b
y, uds1 :: UsageDetails
uds1) <- a -> SpecM (b, UsageDetails)
f a
x
(ys :: [b]
ys, uds2 :: UsageDetails
uds2) <- (a -> SpecM (b, UsageDetails)) -> [a] -> SpecM ([b], UsageDetails)
forall a b.
(a -> SpecM (b, UsageDetails)) -> [a] -> SpecM ([b], UsageDetails)
mapAndCombineSM a -> SpecM (b, UsageDetails)
f [a]
xs
([b], UsageDetails) -> SpecM ([b], UsageDetails)
forall (m :: * -> *) a. Monad m => a -> m a
return (b
yb -> [b] -> [b]
forall a. a -> [a] -> [a]
:[b]
ys, UsageDetails
uds1 UsageDetails -> UsageDetails -> UsageDetails
`plusUDs` UsageDetails
uds2)
extendTvSubstList :: SpecEnv -> [(TyVar,Type)] -> SpecEnv
extendTvSubstList :: SpecEnv -> [(Id, Type)] -> SpecEnv
extendTvSubstList env :: SpecEnv
env tv_binds :: [(Id, Type)]
tv_binds
= SpecEnv
env { se_subst :: Subst
se_subst = Subst -> [(Id, Type)] -> Subst
CoreSubst.extendTvSubstList (SpecEnv -> Subst
se_subst SpecEnv
env) [(Id, Type)]
tv_binds }
substTy :: SpecEnv -> Type -> Type
substTy :: SpecEnv -> Type -> Type
substTy env :: SpecEnv
env ty :: Type
ty = Subst -> Type -> Type
CoreSubst.substTy (SpecEnv -> Subst
se_subst SpecEnv
env) Type
ty
substCo :: SpecEnv -> Coercion -> Coercion
substCo :: SpecEnv -> Coercion -> Coercion
substCo env :: SpecEnv
env co :: Coercion
co = Subst -> Coercion -> Coercion
CoreSubst.substCo (SpecEnv -> Subst
se_subst SpecEnv
env) Coercion
co
substBndr :: SpecEnv -> CoreBndr -> (SpecEnv, CoreBndr)
substBndr :: SpecEnv -> Id -> (SpecEnv, Id)
substBndr env :: SpecEnv
env bs :: Id
bs = case Subst -> Id -> (Subst, Id)
CoreSubst.substBndr (SpecEnv -> Subst
se_subst SpecEnv
env) Id
bs of
(subst' :: Subst
subst', bs' :: Id
bs') -> (SpecEnv
env { se_subst :: Subst
se_subst = Subst
subst' }, Id
bs')
substBndrs :: SpecEnv -> [CoreBndr] -> (SpecEnv, [CoreBndr])
substBndrs :: SpecEnv -> [Id] -> (SpecEnv, [Id])
substBndrs env :: SpecEnv
env bs :: [Id]
bs = case Subst -> [Id] -> (Subst, [Id])
CoreSubst.substBndrs (SpecEnv -> Subst
se_subst SpecEnv
env) [Id]
bs of
(subst' :: Subst
subst', bs' :: [Id]
bs') -> (SpecEnv
env { se_subst :: Subst
se_subst = Subst
subst' }, [Id]
bs')
cloneBindSM :: SpecEnv -> CoreBind -> SpecM (SpecEnv, SpecEnv, CoreBind)
cloneBindSM :: SpecEnv -> Bind Id -> SpecM (SpecEnv, SpecEnv, Bind Id)
cloneBindSM env :: SpecEnv
env@(SE { se_subst :: SpecEnv -> Subst
se_subst = Subst
subst, se_interesting :: SpecEnv -> VarSet
se_interesting = VarSet
interesting }) (NonRec bndr :: Id
bndr rhs :: Expr Id
rhs)
= do { UniqSupply
us <- SpecM UniqSupply
forall (m :: * -> *). MonadUnique m => m UniqSupply
getUniqueSupplyM
; let (subst' :: Subst
subst', bndr' :: Id
bndr') = Subst -> UniqSupply -> Id -> (Subst, Id)
CoreSubst.cloneIdBndr Subst
subst UniqSupply
us Id
bndr
interesting' :: VarSet
interesting' | SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
rhs
= VarSet
interesting VarSet -> Id -> VarSet
`extendVarSet` Id
bndr'
| Bool
otherwise = VarSet
interesting
; (SpecEnv, SpecEnv, Bind Id) -> SpecM (SpecEnv, SpecEnv, Bind Id)
forall (m :: * -> *) a. Monad m => a -> m a
return (SpecEnv
env, SpecEnv
env { se_subst :: Subst
se_subst = Subst
subst', se_interesting :: VarSet
se_interesting = VarSet
interesting' }
, Id -> Expr Id -> Bind Id
forall b. b -> Expr b -> Bind b
NonRec Id
bndr' Expr Id
rhs) }
cloneBindSM env :: SpecEnv
env@(SE { se_subst :: SpecEnv -> Subst
se_subst = Subst
subst, se_interesting :: SpecEnv -> VarSet
se_interesting = VarSet
interesting }) (Rec pairs :: [(Id, Expr Id)]
pairs)
= do { UniqSupply
us <- SpecM UniqSupply
forall (m :: * -> *). MonadUnique m => m UniqSupply
getUniqueSupplyM
; let (subst' :: Subst
subst', bndrs' :: [Id]
bndrs') = Subst -> UniqSupply -> [Id] -> (Subst, [Id])
CoreSubst.cloneRecIdBndrs Subst
subst UniqSupply
us (((Id, Expr Id) -> Id) -> [(Id, Expr Id)] -> [Id]
forall a b. (a -> b) -> [a] -> [b]
map (Id, Expr Id) -> Id
forall a b. (a, b) -> a
fst [(Id, Expr Id)]
pairs)
env' :: SpecEnv
env' = SpecEnv
env { se_subst :: Subst
se_subst = Subst
subst'
, se_interesting :: VarSet
se_interesting = VarSet
interesting VarSet -> [Id] -> VarSet
`extendVarSetList`
[ Id
v | (v :: Id
v,r :: Expr Id
r) <- [(Id, Expr Id)]
pairs, SpecEnv -> Expr Id -> Bool
interestingDict SpecEnv
env Expr Id
r ] }
; (SpecEnv, SpecEnv, Bind Id) -> SpecM (SpecEnv, SpecEnv, Bind Id)
forall (m :: * -> *) a. Monad m => a -> m a
return (SpecEnv
env', SpecEnv
env', [(Id, Expr Id)] -> Bind Id
forall b. [(b, Expr b)] -> Bind b
Rec ([Id]
bndrs' [Id] -> [Expr Id] -> [(Id, Expr Id)]
forall a b. [a] -> [b] -> [(a, b)]
`zip` ((Id, Expr Id) -> Expr Id) -> [(Id, Expr Id)] -> [Expr Id]
forall a b. (a -> b) -> [a] -> [b]
map (Id, Expr Id) -> Expr Id
forall a b. (a, b) -> b
snd [(Id, Expr Id)]
pairs)) }
newDictBndr :: SpecEnv -> CoreBndr -> SpecM CoreBndr
newDictBndr :: SpecEnv -> Id -> SpecM Id
newDictBndr env :: SpecEnv
env b :: Id
b = do { Unique
uniq <- SpecM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let n :: Name
n = Id -> Name
idName Id
b
ty' :: Type
ty' = SpecEnv -> Type -> Type
substTy SpecEnv
env (Id -> Type
idType Id
b)
; Id -> SpecM Id
forall (m :: * -> *) a. Monad m => a -> m a
return (OccName -> Unique -> Type -> SrcSpan -> Id
mkUserLocalOrCoVar (Name -> OccName
nameOccName Name
n) Unique
uniq Type
ty' (Name -> SrcSpan
forall a. NamedThing a => a -> SrcSpan
getSrcSpan Name
n)) }
newSpecIdSM :: Id -> Type -> Maybe JoinArity -> SpecM Id
newSpecIdSM :: Id -> Type -> Maybe Int -> SpecM Id
newSpecIdSM old_id :: Id
old_id new_ty :: Type
new_ty join_arity_maybe :: Maybe Int
join_arity_maybe
= do { Unique
uniq <- SpecM Unique
forall (m :: * -> *). MonadUnique m => m Unique
getUniqueM
; let name :: Name
name = Id -> Name
idName Id
old_id
new_occ :: OccName
new_occ = OccName -> OccName
mkSpecOcc (Name -> OccName
nameOccName Name
name)
new_id :: Id
new_id = OccName -> Unique -> Type -> SrcSpan -> Id
mkUserLocalOrCoVar OccName
new_occ Unique
uniq Type
new_ty (Name -> SrcSpan
forall a. NamedThing a => a -> SrcSpan
getSrcSpan Name
name)
Id -> Maybe Int -> Id
`asJoinId_maybe` Maybe Int
join_arity_maybe
; Id -> SpecM Id
forall (m :: * -> *) a. Monad m => a -> m a
return Id
new_id }