module GHC.Core.Opt.Pipeline ( core2core, simplifyExpr ) where
#include "HsVersions.h"
import GHC.Prelude
import GHC.Driver.Session
import GHC.Driver.Ppr
import GHC.Driver.Plugins ( withPlugins, installCoreToDos )
import GHC.Driver.Env
import GHC.Platform.Ways ( hasWay, Way(WayProf) )
import GHC.Core
import GHC.Core.Opt.CSE ( cseProgram )
import GHC.Core.Rules ( mkRuleBase, unionRuleBase,
extendRuleBaseList, ruleCheckProgram, addRuleInfo,
getRules, initRuleOpts )
import GHC.Core.Ppr ( pprCoreBindings, pprCoreExpr )
import GHC.Core.Opt.OccurAnal ( occurAnalysePgm, occurAnalyseExpr )
import GHC.Core.Stats ( coreBindsSize, coreBindsStats, exprSize )
import GHC.Core.Utils ( mkTicks, stripTicksTop, dumpIdInfoOfProgram )
import GHC.Core.Lint ( endPass, lintPassResult, dumpPassResult,
lintAnnots )
import GHC.Core.Opt.Simplify ( simplTopBinds, simplExpr, simplRules )
import GHC.Core.Opt.Simplify.Utils ( simplEnvForGHCi, activeRule, activeUnfolding )
import GHC.Core.Opt.Simplify.Env
import GHC.Core.Opt.Simplify.Monad
import GHC.Core.Opt.Monad
import GHC.Core.Opt.FloatIn ( floatInwards )
import GHC.Core.Opt.FloatOut ( floatOutwards )
import GHC.Core.Opt.LiberateCase ( liberateCase )
import GHC.Core.Opt.StaticArgs ( doStaticArgs )
import GHC.Core.Opt.Specialise ( specProgram)
import GHC.Core.Opt.SpecConstr ( specConstrProgram)
import GHC.Core.Opt.DmdAnal
import GHC.Core.Opt.CprAnal ( cprAnalProgram )
import GHC.Core.Opt.CallArity ( callArityAnalProgram )
import GHC.Core.Opt.Exitify ( exitifyProgram )
import GHC.Core.Opt.WorkWrap ( wwTopBinds )
import GHC.Core.Opt.CallerCC ( addCallerCostCentres )
import GHC.Core.Seq (seqBinds)
import GHC.Core.FamInstEnv
import qualified GHC.Utils.Error as Err
import GHC.Utils.Error ( withTiming )
import GHC.Utils.Logger as Logger
import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Unit.External
import GHC.Unit.Module.Env
import GHC.Unit.Module.ModGuts
import GHC.Unit.Module.Deps
import GHC.Runtime.Context
import GHC.Types.SrcLoc
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Basic
import GHC.Types.Demand ( zapDmdEnvSig )
import GHC.Types.Var.Set
import GHC.Types.Var.Env
import GHC.Types.Tickish
import GHC.Types.Unique.Supply ( UniqSupply )
import GHC.Types.Unique.FM
import GHC.Types.Name.Ppr
import Control.Monad
import qualified GHC.LanguageExtensions as LangExt
core2core :: HscEnv -> ModGuts -> IO ModGuts
core2core hsc_env guts@(ModGuts { mg_module = mod
, mg_loc = loc
, mg_deps = deps
, mg_rdr_env = rdr_env })
= do { let builtin_passes = getCoreToDo logger dflags
orph_mods = mkModuleSet (mod : dep_orphs deps)
uniq_mask = 's'
;
; (guts2, stats) <- runCoreM hsc_env hpt_rule_base uniq_mask mod
orph_mods print_unqual loc $
do { hsc_env' <- getHscEnv
; all_passes <- withPlugins hsc_env'
installCoreToDos
builtin_passes
; runCorePasses all_passes guts }
; Logger.dumpIfSet_dyn logger dflags Opt_D_dump_simpl_stats
"Grand total simplifier statistics"
FormatText
(pprSimplCount stats)
; return guts2 }
where
logger = hsc_logger hsc_env
dflags = hsc_dflags hsc_env
home_pkg_rules = hptRules hsc_env (dep_mods deps)
hpt_rule_base = mkRuleBase home_pkg_rules
print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env
getCoreToDo :: Logger -> DynFlags -> [CoreToDo]
getCoreToDo logger dflags
= flatten_todos core_todo
where
opt_level = optLevel dflags
phases = simplPhases dflags
max_iter = maxSimplIterations dflags
rule_check = ruleCheck dflags
call_arity = gopt Opt_CallArity dflags
exitification = gopt Opt_Exitification dflags
strictness = gopt Opt_Strictness dflags
full_laziness = gopt Opt_FullLaziness dflags
do_specialise = gopt Opt_Specialise dflags
do_float_in = gopt Opt_FloatIn dflags
cse = gopt Opt_CSE dflags
spec_constr = gopt Opt_SpecConstr dflags
liberate_case = gopt Opt_LiberateCase dflags
late_dmd_anal = gopt Opt_LateDmdAnal dflags
late_specialise = gopt Opt_LateSpecialise dflags
static_args = gopt Opt_StaticArgumentTransformation dflags
rules_on = gopt Opt_EnableRewriteRules dflags
eta_expand_on = gopt Opt_DoLambdaEtaExpansion dflags
pre_inline_on = gopt Opt_SimplPreInlining dflags
ww_on = gopt Opt_WorkerWrapper dflags
static_ptrs = xopt LangExt.StaticPointers dflags
profiling = ways dflags `hasWay` WayProf
maybe_rule_check phase = runMaybe rule_check (CoreDoRuleCheck phase)
maybe_strictness_before (Phase phase)
| phase `elem` strictnessBefore dflags = CoreDoDemand
maybe_strictness_before _
= CoreDoNothing
base_mode = SimplMode { sm_phase = panic "base_mode"
, sm_names = []
, sm_dflags = dflags
, sm_logger = logger
, sm_uf_opts = unfoldingOpts dflags
, sm_rules = rules_on
, sm_eta_expand = eta_expand_on
, sm_inline = True
, sm_case_case = True
, sm_pre_inline = pre_inline_on
}
simpl_phase phase name iter
= CoreDoPasses
$ [ maybe_strictness_before phase
, CoreDoSimplify iter
(base_mode { sm_phase = phase
, sm_names = [name] })
, maybe_rule_check phase ]
simplify name = simpl_phase FinalPhase name max_iter
simpl_gently = CoreDoSimplify max_iter
(base_mode { sm_phase = InitialPhase
, sm_names = ["Gentle"]
, sm_rules = rules_on
, sm_inline = True
, sm_case_case = False })
dmd_cpr_ww = if ww_on then [CoreDoDemand,CoreDoCpr,CoreDoWorkerWrapper]
else [CoreDoDemand,CoreDoCpr]
demand_analyser = (CoreDoPasses (
dmd_cpr_ww ++
[simplify "post-worker-wrapper"]
))
static_ptrs_float_outwards =
runWhen static_ptrs $ CoreDoPasses
[ simpl_gently
, CoreDoFloatOutwards FloatOutSwitches
{ floatOutLambdas = Just 0
, floatOutConstants = True
, floatOutOverSatApps = False
, floatToTopLevelOnly = True
}
]
add_caller_ccs =
runWhen (profiling && not (null $ callerCcFilters dflags)) CoreAddCallerCcs
core_todo =
if opt_level == 0 then
[ static_ptrs_float_outwards,
CoreDoSimplify max_iter
(base_mode { sm_phase = FinalPhase
, sm_names = ["Non-opt simplification"] })
, add_caller_ccs
]
else [
runWhen static_args (CoreDoPasses [ simpl_gently, CoreDoStaticArgs ]),
simpl_gently,
runWhen do_specialise CoreDoSpecialising,
if full_laziness then
CoreDoFloatOutwards FloatOutSwitches {
floatOutLambdas = Just 0,
floatOutConstants = True,
floatOutOverSatApps = False,
floatToTopLevelOnly = False }
else
static_ptrs_float_outwards,
CoreDoPasses [ simpl_phase (Phase phase) "main" max_iter
| phase <- [phases, phases1 .. 1] ],
simpl_phase (Phase 0) "main" (max max_iter 3),
runWhen do_float_in CoreDoFloatInwards,
runWhen call_arity $ CoreDoPasses
[ CoreDoCallArity
, simplify "post-call-arity"
],
runWhen strictness demand_analyser,
runWhen exitification CoreDoExitify,
runWhen full_laziness $
CoreDoFloatOutwards FloatOutSwitches {
floatOutLambdas = floatLamArgs dflags,
floatOutConstants = True,
floatOutOverSatApps = True,
floatToTopLevelOnly = False },
runWhen cse CoreCSE,
runWhen do_float_in CoreDoFloatInwards,
simplify "final",
maybe_rule_check FinalPhase,
runWhen liberate_case $ CoreDoPasses
[ CoreLiberateCase, simplify "post-liberate-case" ],
runWhen spec_constr $ CoreDoPasses
[ CoreDoSpecConstr, simplify "post-spec-constr"],
maybe_rule_check FinalPhase,
runWhen late_specialise $ CoreDoPasses
[ CoreDoSpecialising, simplify "post-late-spec"],
runWhen ((liberate_case || spec_constr) && cse) $ CoreDoPasses
[ CoreCSE, simplify "post-final-cse" ],
runWhen late_dmd_anal $ CoreDoPasses (
dmd_cpr_ww ++ [simplify "post-late-ww"]
),
runWhen (strictness || late_dmd_anal) CoreDoDemand,
maybe_rule_check FinalPhase,
add_caller_ccs
]
flatten_todos [] = []
flatten_todos (CoreDoNothing : rest) = flatten_todos rest
flatten_todos (CoreDoPasses passes : rest) =
flatten_todos passes ++ flatten_todos rest
flatten_todos (todo : rest) = todo : flatten_todos rest
runCorePasses :: [CoreToDo] -> ModGuts -> CoreM ModGuts
runCorePasses passes guts
= foldM do_pass guts passes
where
do_pass guts CoreDoNothing = return guts
do_pass guts (CoreDoPasses ps) = runCorePasses ps guts
do_pass guts pass = do
dflags <- getDynFlags
logger <- getLogger
withTiming logger dflags (ppr pass <+> brackets (ppr mod))
(const ()) $ do
guts' <- lintAnnots (ppr pass) (doCorePass pass) guts
endPass pass (mg_binds guts') (mg_rules guts')
return guts'
mod = mg_module guts
doCorePass :: CoreToDo -> ModGuts -> CoreM ModGuts
doCorePass pass guts = do
logger <- getLogger
case pass of
CoreDoSimplify {} ->
simplifyPgm pass guts
CoreCSE ->
doPass cseProgram guts
CoreLiberateCase ->
doPassD liberateCase guts
CoreDoFloatInwards ->
floatInwards guts
CoreDoFloatOutwards f ->
doPassDUM (floatOutwards logger f) guts
CoreDoStaticArgs ->
doPassU doStaticArgs guts
CoreDoCallArity ->
doPassD callArityAnalProgram guts
CoreDoExitify ->
doPass exitifyProgram guts
CoreDoDemand ->
doPassDFRM (dmdAnal logger) guts
CoreDoCpr ->
doPassDFM (cprAnalProgram logger) guts
CoreDoWorkerWrapper ->
doPassDFU wwTopBinds guts
CoreDoSpecialising ->
specProgram guts
CoreDoSpecConstr ->
specConstrProgram guts
CoreAddCallerCcs ->
addCallerCostCentres guts
CoreDoPrintCore -> observe (printCore logger) guts
CoreDoRuleCheck phase pat -> ruleCheckPass phase pat guts
CoreDoNothing -> return guts
CoreDoPasses passes -> runCorePasses passes guts
CoreDoPluginPass _ p -> p guts
CoreDesugar -> pprPanic "doCorePass" (ppr pass)
CoreDesugarOpt -> pprPanic "doCorePass" (ppr pass)
CoreTidy -> pprPanic "doCorePass" (ppr pass)
CorePrep -> pprPanic "doCorePass" (ppr pass)
CoreOccurAnal -> pprPanic "doCorePass" (ppr pass)
printCore :: Logger -> DynFlags -> CoreProgram -> IO ()
printCore logger dflags binds
= Logger.dumpIfSet logger dflags True "Print Core" (pprCoreBindings binds)
ruleCheckPass :: CompilerPhase -> String -> ModGuts -> CoreM ModGuts
ruleCheckPass current_phase pat guts = do
dflags <- getDynFlags
logger <- getLogger
withTiming logger dflags (text "RuleCheck"<+>brackets (ppr $ mg_module guts))
(const ()) $ do
rb <- getRuleBase
vis_orphs <- getVisibleOrphanMods
let rule_fn fn = getRules (RuleEnv rb vis_orphs) fn
++ (mg_rules guts)
let ropts = initRuleOpts dflags
liftIO $ putLogMsg logger dflags NoReason Err.SevDump noSrcSpan
$ withPprStyle defaultDumpStyle
(ruleCheckProgram ropts current_phase pat
rule_fn (mg_binds guts))
return guts
doPassDUM :: (DynFlags -> UniqSupply -> CoreProgram -> IO CoreProgram) -> ModGuts -> CoreM ModGuts
doPassDUM do_pass = doPassM $ \binds -> do
dflags <- getDynFlags
us <- getUniqueSupplyM
liftIO $ do_pass dflags us binds
doPassDM :: (DynFlags -> CoreProgram -> IO CoreProgram) -> ModGuts -> CoreM ModGuts
doPassDM do_pass = doPassDUM (\dflags -> const (do_pass dflags))
doPassD :: (DynFlags -> CoreProgram -> CoreProgram) -> ModGuts -> CoreM ModGuts
doPassD do_pass = doPassDM (\dflags -> return . do_pass dflags)
doPassDU :: (DynFlags -> UniqSupply -> CoreProgram -> CoreProgram) -> ModGuts -> CoreM ModGuts
doPassDU do_pass = doPassDUM (\dflags us -> return . do_pass dflags us)
doPassU :: (UniqSupply -> CoreProgram -> CoreProgram) -> ModGuts -> CoreM ModGuts
doPassU do_pass = doPassDU (const do_pass)
doPassDFM :: (DynFlags -> FamInstEnvs -> CoreProgram -> IO CoreProgram) -> ModGuts -> CoreM ModGuts
doPassDFM do_pass guts = do
dflags <- getDynFlags
p_fam_env <- getPackageFamInstEnv
let fam_envs = (p_fam_env, mg_fam_inst_env guts)
doPassM (liftIO . do_pass dflags fam_envs) guts
doPassDFRM :: (DynFlags -> FamInstEnvs -> [CoreRule] -> CoreProgram -> IO CoreProgram) -> ModGuts -> CoreM ModGuts
doPassDFRM do_pass guts = do
dflags <- getDynFlags
p_fam_env <- getPackageFamInstEnv
let fam_envs = (p_fam_env, mg_fam_inst_env guts)
doPassM (liftIO . do_pass dflags fam_envs (mg_rules guts)) guts
doPassDFU :: (DynFlags -> FamInstEnvs -> UniqSupply -> CoreProgram -> CoreProgram) -> ModGuts -> CoreM ModGuts
doPassDFU do_pass guts = do
dflags <- getDynFlags
us <- getUniqueSupplyM
p_fam_env <- getPackageFamInstEnv
let fam_envs = (p_fam_env, mg_fam_inst_env guts)
doPass (do_pass dflags fam_envs us) guts
doPassM :: Monad m => (CoreProgram -> m CoreProgram) -> ModGuts -> m ModGuts
doPassM bind_f guts = do
binds' <- bind_f (mg_binds guts)
return (guts { mg_binds = binds' })
doPass :: (CoreProgram -> CoreProgram) -> ModGuts -> CoreM ModGuts
doPass bind_f guts = return $ guts { mg_binds = bind_f (mg_binds guts) }
observe :: (DynFlags -> CoreProgram -> IO a) -> ModGuts -> CoreM ModGuts
observe do_pass = doPassM $ \binds -> do
dflags <- getDynFlags
_ <- liftIO $ do_pass dflags binds
return binds
simplifyExpr :: HscEnv
-> CoreExpr
-> IO CoreExpr
simplifyExpr hsc_env expr
= withTiming logger dflags (text "Simplify [expr]") (const ()) $
do { eps <- hscEPS hsc_env ;
; let rule_env = mkRuleEnv (eps_rule_base eps) []
fi_env = ( eps_fam_inst_env eps
, extendFamInstEnvList emptyFamInstEnv $
snd $ ic_instances $ hsc_IC hsc_env )
simpl_env = simplEnvForGHCi logger dflags
; let sz = exprSize expr
; (expr', counts) <- initSmpl logger dflags rule_env fi_env sz $
simplExprGently simpl_env expr
; Logger.dumpIfSet logger dflags (dopt Opt_D_dump_simpl_stats dflags)
"Simplifier statistics" (pprSimplCount counts)
; Logger.dumpIfSet_dyn logger dflags Opt_D_dump_simpl "Simplified expression"
FormatCore
(pprCoreExpr expr')
; return expr'
}
where
dflags = hsc_dflags hsc_env
logger = hsc_logger hsc_env
simplExprGently :: SimplEnv -> CoreExpr -> SimplM CoreExpr
simplExprGently env expr = do
expr1 <- simplExpr env (occurAnalyseExpr expr)
simplExpr env (occurAnalyseExpr expr1)
simplifyPgm :: CoreToDo -> ModGuts -> CoreM ModGuts
simplifyPgm pass guts
= do { hsc_env <- getHscEnv
; rb <- getRuleBase
; liftIOWithCount $
simplifyPgmIO pass hsc_env rb guts }
simplifyPgmIO :: CoreToDo
-> HscEnv
-> RuleBase
-> ModGuts
-> IO (SimplCount, ModGuts)
simplifyPgmIO pass@(CoreDoSimplify max_iterations mode)
hsc_env hpt_rule_base
guts@(ModGuts { mg_module = this_mod
, mg_rdr_env = rdr_env
, mg_deps = deps
, mg_binds = binds, mg_rules = rules
, mg_fam_inst_env = fam_inst_env })
= do { (termination_msg, it_count, counts_out, guts')
<- do_iteration 1 [] binds rules
; Logger.dumpIfSet logger dflags (dopt Opt_D_verbose_core2core dflags &&
dopt Opt_D_dump_simpl_stats dflags)
"Simplifier statistics for following pass"
(vcat [text termination_msg <+> text "after" <+> ppr it_count
<+> text "iterations",
blankLine,
pprSimplCount counts_out])
; return (counts_out, guts')
}
where
dflags = hsc_dflags hsc_env
logger = hsc_logger hsc_env
print_unqual = mkPrintUnqualified (hsc_unit_env hsc_env) rdr_env
simpl_env = mkSimplEnv mode
active_rule = activeRule mode
active_unf = activeUnfolding mode
do_iteration :: Int --UniqSupply
-> [SimplCount]
-> CoreProgram
-> [CoreRule]
-> IO (String, Int, SimplCount, ModGuts)
do_iteration iteration_no counts_so_far binds rules
| iteration_no > max_iterations
= WARN( debugIsOn && (max_iterations > 2)
, hang (text "Simplifier bailing out after" <+> int max_iterations
<+> text "iterations"
<+> (brackets $ hsep $ punctuate comma $
map (int . simplCountN) (reverse counts_so_far)))
2 (text "Size =" <+> ppr (coreBindsStats binds)))
return ( "Simplifier baled out", iteration_no 1
, totalise counts_so_far
, guts { mg_binds = binds, mg_rules = rules } )
| let sz = coreBindsSize binds
, () <- sz `seq` ()
= do {
let { tagged_binds =
occurAnalysePgm this_mod active_unf active_rule rules
binds
} ;
Logger.dumpIfSet_dyn logger dflags Opt_D_dump_occur_anal "Occurrence analysis"
FormatCore
(pprCoreBindings tagged_binds);
eps <- hscEPS hsc_env ;
let { rule_base1 = unionRuleBase hpt_rule_base (eps_rule_base eps)
; rule_base2 = extendRuleBaseList rule_base1 rules
; fam_envs = (eps_fam_inst_env eps, fam_inst_env)
; vis_orphs = this_mod : dep_orphs deps } ;
((binds1, rules1), counts1) <-
initSmpl logger dflags (mkRuleEnv rule_base2 vis_orphs) fam_envs sz $
do { (floats, env1) <-
simplTopBinds simpl_env tagged_binds
; rules1 <- simplRules env1 Nothing rules Nothing
; return (getTopFloatBinds floats, rules1) } ;
if isZeroSimplCount counts1 then
return ( "Simplifier reached fixed point", iteration_no
, totalise (counts1 : counts_so_far)
, guts { mg_binds = binds1, mg_rules = rules1 } )
else do {
let { binds2 = shortOutIndirections binds1 } ;
dump_end_iteration logger dflags print_unqual iteration_no counts1 binds2 rules1 ;
lintPassResult hsc_env pass binds2 ;
do_iteration (iteration_no + 1) (counts1:counts_so_far) binds2 rules1
} }
#if __GLASGOW_HASKELL__ <= 810
| otherwise = panic "do_iteration"
#endif
where
totalise :: [SimplCount] -> SimplCount
totalise = foldr (\c acc -> acc `plusSimplCount` c)
(zeroSimplCount dflags)
simplifyPgmIO _ _ _ _ = panic "simplifyPgmIO"
dump_end_iteration :: Logger -> DynFlags -> PrintUnqualified -> Int
-> SimplCount -> CoreProgram -> [CoreRule] -> IO ()
dump_end_iteration logger dflags print_unqual iteration_no counts binds rules
= dumpPassResult logger dflags print_unqual mb_flag hdr pp_counts binds rules
where
mb_flag | dopt Opt_D_dump_simpl_iterations dflags = Just Opt_D_dump_simpl_iterations
| otherwise = Nothing
hdr = text "Simplifier iteration=" <> int iteration_no
pp_counts = vcat [ text "---- Simplifier counts for" <+> hdr
, pprSimplCount counts
, text "---- End of simplifier counts for" <+> hdr ]
type IndEnv = IdEnv (Id, [CoreTickish])
shortOutIndirections :: CoreProgram -> CoreProgram
shortOutIndirections binds
| isEmptyVarEnv ind_env = binds
| no_need_to_flatten = binds'
| otherwise = [Rec (flattenBinds binds')]
where
ind_env = makeIndEnv binds
exp_ids = map fst $ nonDetEltsUFM ind_env
exp_id_set = mkVarSet exp_ids
no_need_to_flatten = all (null . ruleInfoRules . idSpecialisation) exp_ids
binds' = concatMap zap binds
zap (NonRec bndr rhs) = [NonRec b r | (b,r) <- zapPair (bndr,rhs)]
zap (Rec pairs) = [Rec (concatMap zapPair pairs)]
zapPair (bndr, rhs)
| bndr `elemVarSet` exp_id_set
= []
| Just (exp_id, ticks) <- lookupVarEnv ind_env bndr
, (exp_id', lcl_id') <- transferIdInfo exp_id bndr
=
[ (exp_id', mkTicks ticks rhs),
(lcl_id', Var exp_id') ]
| otherwise
= [(bndr,rhs)]
makeIndEnv :: [CoreBind] -> IndEnv
makeIndEnv binds
= foldl' add_bind emptyVarEnv binds
where
add_bind :: IndEnv -> CoreBind -> IndEnv
add_bind env (NonRec exported_id rhs) = add_pair env (exported_id, rhs)
add_bind env (Rec pairs) = foldl' add_pair env pairs
add_pair :: IndEnv -> (Id,CoreExpr) -> IndEnv
add_pair env (exported_id, exported)
| (ticks, Var local_id) <- stripTicksTop tickishFloatable exported
, shortMeOut env exported_id local_id
= extendVarEnv env local_id (exported_id, ticks)
add_pair env _ = env
shortMeOut :: IndEnv -> Id -> Id -> Bool
shortMeOut ind_env exported_id local_id
= if isExportedId exported_id &&
isLocalId local_id &&
not (isExportedId local_id) &&
not (local_id `elemVarEnv` ind_env)
then
if hasShortableIdInfo exported_id
then True
else WARN( True, text "Not shorting out:" <+> ppr exported_id )
False
else
False
hasShortableIdInfo :: Id -> Bool
hasShortableIdInfo id
= isEmptyRuleInfo (ruleInfo info)
&& isDefaultInlinePragma (inlinePragInfo info)
&& not (isStableUnfolding (unfoldingInfo info))
where
info = idInfo id
transferIdInfo :: Id -> Id -> (Id, Id)
transferIdInfo exported_id local_id
= ( modifyIdInfo transfer exported_id
, local_id `setInlinePragma` defaultInlinePragma )
where
local_info = idInfo local_id
transfer exp_info = exp_info `setStrictnessInfo` strictnessInfo local_info
`setCprInfo` cprInfo local_info
`setUnfoldingInfo` unfoldingInfo local_info
`setInlinePragInfo` inlinePragInfo local_info
`setRuleInfo` addRuleInfo (ruleInfo exp_info) new_info
new_info = setRuleInfoHead (idName exported_id)
(ruleInfo local_info)
dmdAnal :: Logger -> DynFlags -> FamInstEnvs -> [CoreRule] -> CoreProgram -> IO CoreProgram
dmdAnal logger dflags fam_envs rules binds = do
let !opts = DmdAnalOpts
{ dmd_strict_dicts = gopt Opt_DictsStrict dflags
}
binds_plus_dmds = dmdAnalProgram opts fam_envs rules binds
Logger.dumpIfSet_dyn logger dflags Opt_D_dump_str_signatures "Strictness signatures" FormatText $
dumpIdInfoOfProgram (ppr . zapDmdEnvSig . strictnessInfo) binds_plus_dmds
seqBinds binds_plus_dmds `seq` return binds_plus_dmds