X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2FsimplCore%2FSimplCore.lhs;h=1a634d5e0ebe86efcca3e9b39d5be48b533bcfc4;hp=dd0422b5138383d896ffec63c9ad6418b3e8c03e;hb=f2aaae9757e7532485c97f6c9a9ed5437542d1dd;hpb=e2ad220248f5e29bca7c42903780a687086e6b65 diff --git a/compiler/simplCore/SimplCore.lhs b/compiler/simplCore/SimplCore.lhs index dd0422b..1a634d5 100644 --- a/compiler/simplCore/SimplCore.lhs +++ b/compiler/simplCore/SimplCore.lhs @@ -4,13 +4,6 @@ \section[SimplCore]{Driver for simplifying @Core@ programs} \begin{code} -{-# OPTIONS -w #-} --- The above warning supression flag is a temporary kludge. --- While working on this module you are encouraged to remove it and fix --- any warnings in the module. See --- http://hackage.haskell.org/trac/ghc/wiki/Commentary/CodingStyle#Warnings --- for details - module SimplCore ( core2core, simplifyExpr ) where #include "HsVersions.h" @@ -21,31 +14,24 @@ import CoreSubst import HscTypes import CSE ( cseProgram ) import Rules ( RuleBase, emptyRuleBase, mkRuleBase, unionRuleBase, - extendRuleBaseList, pprRuleBase, pprRulesForUser, - ruleCheckProgram, rulesOfBinds, - addSpecInfo, addIdSpecialisations ) -import PprCore ( pprCoreBindings, pprCoreExpr, pprRules ) + extendRuleBaseList, ruleCheckProgram, addSpecInfo, ) +import PprCore ( pprCoreBindings, pprCoreExpr ) import OccurAnal ( occurAnalysePgm, occurAnalyseExpr ) import IdInfo import CoreUtils ( coreBindsSize ) import Simplify ( simplTopBinds, simplExpr ) -import SimplUtils ( simplEnvForGHCi, simplEnvForRules ) +import SimplUtils ( simplEnvForGHCi, activeRule ) import SimplEnv import SimplMonad import CoreMonad import qualified ErrUtils as Err -import CoreLint import FloatIn ( floatInwards ) import FloatOut ( floatOutwards ) import FamInstEnv import Id -import DataCon -import TyCon ( tyConDataCons ) -import Class ( classSelIds ) -import BasicTypes ( CompilerPhase, isActive, isDefaultInlinePragma ) +import BasicTypes ( CompilerPhase, isDefaultInlinePragma ) import VarSet import VarEnv -import NameEnv ( lookupNameEnv ) import LiberateCase ( liberateCase ) import SAT ( doStaticArgs ) import Specialise ( specProgram) @@ -59,9 +45,6 @@ import Util import UniqSupply ( UniqSupply, mkSplitUniqSupply, splitUniqSupply ) import Outputable import Control.Monad -import Data.List -import System.IO -import Maybes \end{code} %************************************************************************ @@ -71,64 +54,31 @@ import Maybes %************************************************************************ \begin{code} -core2core :: HscEnv - -> ModGuts - -> IO ModGuts - -core2core hsc_env guts = do - let dflags = hsc_dflags hsc_env +core2core :: HscEnv -> ModGuts -> IO ModGuts +core2core hsc_env guts + = do { us <- mkSplitUniqSupply 's' + ; (guts2, stats) <- runCoreM hsc_env hpt_rule_base us mod $ + doCorePasses (getCoreToDo dflags) guts - us <- mkSplitUniqSupply 's' - let (cp_us, ru_us) = splitUniqSupply us + ; Err.dumpIfSet_dyn dflags Opt_D_dump_simpl_stats + "Grand total simplifier statistics" + (pprSimplCount stats) - -- COMPUTE THE RULE BASE TO USE - -- See Note [Overall plumbing for rules] in Rules.lhs - (hpt_rule_base, guts1) <- prepareRules hsc_env guts ru_us - - -- Get the module out of the current HscEnv so we can retrieve it from the monad. + ; return guts2 } + where + dflags = hsc_dflags hsc_env + home_pkg_rules = hptRules hsc_env (dep_mods (mg_deps guts)) + hpt_rule_base = mkRuleBase home_pkg_rules + mod = mg_module guts + -- mod: get the module out of the current HscEnv so we can retrieve it from the monad. -- This is very convienent for the users of the monad (e.g. plugins do not have to -- consume the ModGuts to find the module) but somewhat ugly because mg_module may -- _theoretically_ be changed during the Core pipeline (it's part of ModGuts), which -- would mean our cached value would go out of date. - let mod = mg_module guts - (guts2, stats) <- runCoreM hsc_env hpt_rule_base cp_us mod $ do - -- FIND BUILT-IN PASSES - let builtin_core_todos = getCoreToDo dflags - - -- DO THE BUSINESS - doCorePasses builtin_core_todos guts1 - - Err.dumpIfSet_dyn dflags Opt_D_dump_simpl_stats - "Grand total simplifier statistics" - (pprSimplCount stats) - - return guts2 type CorePass = CoreToDo -simplifyExpr :: DynFlags -- includes spec of what core-to-core passes to do - -> CoreExpr - -> IO CoreExpr --- simplifyExpr is called by the driver to simplify an --- expression typed in at the interactive prompt --- --- Also used by Template Haskell -simplifyExpr dflags expr - = do { - ; Err.showPass dflags "Simplify" - - ; us <- mkSplitUniqSupply 's' - - ; let (expr', _counts) = initSmpl dflags emptyRuleBase emptyFamInstEnvs us $ - simplExprGently simplEnvForGHCi expr - - ; Err.dumpIfSet_dyn dflags Opt_D_dump_simpl "Simplified expression" - (pprCoreExpr expr') - - ; return expr' - } - doCorePasses :: [CorePass] -> ModGuts -> CoreM ModGuts doCorePasses passes guts = foldM do_pass guts passes @@ -168,19 +118,20 @@ doCorePass CoreDoWorkerWrapper = {-# SCC "WorkWrap" #-} doPassU wwTopBinds doCorePass CoreDoSpecialising = {-# SCC "Specialise" #-} - doPassU specProgram + specProgram doCorePass CoreDoSpecConstr = {-# SCC "SpecConstr" #-} specConstrProgram -doCorePass (CoreDoVectorisation be) = {-# SCC "Vectorise" #-} - vectorise be +doCorePass CoreDoVectorisation = {-# SCC "Vectorise" #-} + vectorise doCorePass CoreDoGlomBinds = doPassDM glomBinds doCorePass CoreDoPrintCore = observe printCore doCorePass (CoreDoRuleCheck phase pat) = ruleCheck phase pat doCorePass CoreDoNothing = return doCorePass (CoreDoPasses passes) = doCorePasses passes +doCorePass pass = pprPanic "doCorePass" (ppr pass) \end{code} %************************************************************************ @@ -190,6 +141,7 @@ doCorePass (CoreDoPasses passes) = doCorePasses passes %************************************************************************ \begin{code} +printCore :: a -> [CoreBind] -> IO () printCore _ binds = Err.dumpIfSet True "Print Core" (pprCoreBindings binds) ruleCheck :: CompilerPhase -> String -> ModGuts -> CoreM ModGuts @@ -201,11 +153,6 @@ ruleCheck current_phase pat guts = do return guts -doPassDMS :: (DynFlags -> [CoreBind] -> IO (SimplCount, [CoreBind])) -> ModGuts -> CoreM ModGuts -doPassDMS do_pass = doPassM $ \binds -> do - dflags <- getDynFlags - liftIOWithCount $ do_pass dflags binds - doPassDUM :: (DynFlags -> UniqSupply -> [CoreBind] -> IO [CoreBind]) -> ModGuts -> CoreM ModGuts doPassDUM do_pass = doPassM $ \binds -> do dflags <- getDynFlags @@ -231,11 +178,6 @@ doPassM bind_f guts = do binds' <- bind_f (mg_binds guts) return (guts { mg_binds = binds' }) -doPassMG :: Monad m => (ModGuts -> m [CoreBind]) -> ModGuts -> m ModGuts -doPassMG bind_f guts = do - binds' <- bind_f guts - return (guts { mg_binds = binds' }) - doPass :: ([CoreBind] -> [CoreBind]) -> ModGuts -> CoreM ModGuts doPass bind_f guts = return $ guts { mg_binds = bind_f (mg_binds guts) } @@ -243,132 +185,40 @@ doPass bind_f guts = return $ guts { mg_binds = bind_f (mg_binds guts) } observe :: (DynFlags -> [CoreBind] -> IO a) -> ModGuts -> CoreM ModGuts observe do_pass = doPassM $ \binds -> do dflags <- getDynFlags - liftIO $ do_pass dflags binds + _ <- liftIO $ do_pass dflags binds return binds \end{code} %************************************************************************ %* * - Dealing with rules + Gentle simplification %* * %************************************************************************ --- prepareLocalRuleBase takes the CoreBinds and rules defined in this module. --- It attaches those rules that are for local Ids to their binders, and --- returns the remainder attached to Ids in an IdSet. - \begin{code} -prepareRules :: HscEnv - -> ModGuts - -> UniqSupply - -> IO (RuleBase, -- Rule base for imported things, incl - -- (a) rules defined in this module (orphans) - -- (b) rules from other modules in home package - -- but not things from other packages - - ModGuts) -- Modified fields are - -- (a) Bindings have rules attached, - -- and INLINE rules simplified - -- (b) Rules are now just orphan rules - -prepareRules hsc_env@(HscEnv { hsc_dflags = dflags, hsc_HPT = hpt }) - guts@(ModGuts { mg_binds = binds, mg_deps = deps - , mg_rules = local_rules, mg_rdr_env = rdr_env }) - us - = do { us <- mkSplitUniqSupply 'w' - - ; let -- Simplify the local rules; boringly, we need to make an in-scope set - -- from the local binders, to avoid warnings from Simplify.simplVar - local_ids = mkInScopeSet (mkVarSet (bindersOfBinds binds)) - env = setInScopeSet simplEnvForRules local_ids - (simpl_rules, _) = initSmpl dflags emptyRuleBase emptyFamInstEnvs us $ - mapM (simplRule env) local_rules - - ; let (rules_for_locals, rules_for_imps) = partition isLocalRule simpl_rules - - home_pkg_rules = hptRules hsc_env (dep_mods deps) - hpt_rule_base = mkRuleBase home_pkg_rules - binds_w_rules = updateBinders rules_for_locals binds - - - ; Err.dumpIfSet_dyn dflags Opt_D_dump_rules "Transformation rules" - (withPprStyle (mkUserStyle (mkPrintUnqualified dflags rdr_env) AllTheWay) $ - vcat [text "Local rules for local Ids", pprRules simpl_rules, - blankLine, - text "Local rules for imported Ids", pprRuleBase hpt_rule_base]) - - ; return (hpt_rule_base, guts { mg_binds = binds_w_rules, - mg_rules = rules_for_imps }) - } +simplifyExpr :: DynFlags -- includes spec of what core-to-core passes to do + -> CoreExpr + -> IO CoreExpr +-- simplifyExpr is called by the driver to simplify an +-- expression typed in at the interactive prompt +-- +-- Also used by Template Haskell +simplifyExpr dflags expr + = do { + ; Err.showPass dflags "Simplify" --- Note [Attach rules to local ids] --- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ --- Find the rules for locally-defined Ids; then we can attach them --- to the binders in the top-level bindings --- --- Reason --- - It makes the rules easier to look up --- - It means that transformation rules and specialisations for --- locally defined Ids are handled uniformly --- - It keeps alive things that are referred to only from a rule --- (the occurrence analyser knows about rules attached to Ids) --- - It makes sure that, when we apply a rule, the free vars --- of the RHS are more likely to be in scope --- - The imported rules are carried in the in-scope set --- which is extended on each iteration by the new wave of --- local binders; any rules which aren't on the binding will --- thereby get dropped - -updateBinders :: [CoreRule] -> [CoreBind] -> [CoreBind] -updateBinders rules_for_locals binds - = map update_bind binds - where - local_rules = extendRuleBaseList emptyRuleBase rules_for_locals - - update_bind (NonRec b r) = NonRec (add_rules b) r - update_bind (Rec prs) = Rec (mapFst add_rules prs) - - -- See Note [Attach rules to local ids] - -- NB: the binder might have some existing rules, - -- arising from specialisation pragmas - add_rules bndr - | Just rules <- lookupNameEnv local_rules (idName bndr) - = bndr `addIdSpecialisations` rules - | otherwise - = bndr -\end{code} + ; us <- mkSplitUniqSupply 's' -Note [Simplifying the left-hand side of a RULE] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -We must do some gentle simplification on the lhs (template) of each -rule. The case that forced me to add this was the fold/build rule, -which without simplification looked like: - fold k z (build (/\a. g a)) ==> ... -This doesn't match unless you do eta reduction on the build argument. -Similarly for a LHS like - augment g (build h) -we do not want to get - augment (\a. g a) (build h) -otherwise we don't match when given an argument like - augment (\a. h a a) (build h) - -The simplifier does indeed do eta reduction (it's in -Simplify.completeLam) but only if -O is on. + ; let (expr', _counts) = initSmpl dflags emptyRuleBase emptyFamInstEnvs us $ + simplExprGently simplEnvForGHCi expr -\begin{code} -simplRule :: SimplEnv -> CoreRule -> SimplM CoreRule -simplRule env rule@(BuiltinRule {}) - = return rule -simplRule env rule@(Rule { ru_bndrs = bndrs, ru_args = args, ru_rhs = rhs }) - = do (env, bndrs') <- simplBinders env bndrs - args' <- mapM (simplExprGently env) args - rhs' <- simplExprGently env rhs - return (rule { ru_bndrs = bndrs', ru_args = args' - , ru_rhs = occurAnalyseExpr rhs' }) -\end{code} + ; Err.dumpIfSet_dyn dflags Opt_D_dump_simpl "Simplified expression" + (pprCoreExpr expr') + + ; return expr' + } -\begin{code} simplExprGently :: SimplEnv -> CoreExpr -> SimplM CoreExpr -- Simplifies an expression -- does occurrence analysis, then simplification @@ -457,7 +307,7 @@ simplifyPgmIO :: CoreToDo -> ModGuts -> IO (SimplCount, ModGuts) -- New bindings -simplifyPgmIO pass@(CoreDoSimplify mode max_iterations switches) +simplifyPgmIO pass@(CoreDoSimplify max_iterations mode) hsc_env us hpt_rule_base guts@(ModGuts { mg_binds = binds, mg_rules = rules , mg_fam_inst_env = fam_inst_env }) @@ -473,9 +323,11 @@ simplifyPgmIO pass@(CoreDoSimplify mode max_iterations switches) ; return (counts_out, guts') } where - dflags = hsc_dflags hsc_env - dump_phase = dumpSimplPhase dflags mode - sw_chkr = isAmongSimpl switches + dflags = hsc_dflags hsc_env + dump_phase = dumpSimplPhase dflags mode + simpl_env = mkSimplEnv mode + active_rule = activeRule dflags simpl_env + do_iteration :: UniqSupply -> Int -- Counts iterations -> [SimplCount] -- Counts from earlier iterations, reversed @@ -496,15 +348,17 @@ simplifyPgmIO pass@(CoreDoSimplify mode max_iterations switches) -- Subtract 1 from iteration_no to get the -- number of iterations we actually completed - return ("Simplifier baled out", iteration_no - 1, total_counts, - guts { mg_binds = binds, mg_rules = rules }) + return ( "Simplifier baled out", iteration_no - 1 + , totalise counts_so_far + , guts { mg_binds = binds, mg_rules = rules } ) -- Try and force thunks off the binds; significantly reduces -- space usage, especially with -O. JRS, 000620. | let sz = coreBindsSize binds in sz == sz = do { -- Occurrence analysis - let { tagged_binds = {-# SCC "OccAnal" #-} occurAnalysePgm binds rules } ; + let { tagged_binds = {-# SCC "OccAnal" #-} + occurAnalysePgm active_rule rules binds } ; Err.dumpIfSet_dyn dflags Opt_D_dump_occur_anal "Occurrence analysis" (pprCoreBindings tagged_binds); @@ -517,7 +371,6 @@ simplifyPgmIO pass@(CoreDoSimplify mode max_iterations switches) eps <- hscEPS hsc_env ; let { rule_base1 = unionRuleBase hpt_rule_base (eps_rule_base eps) ; rule_base2 = extendRuleBaseList rule_base1 rules - ; simpl_env = mkSimplEnv sw_chkr mode ; simpl_binds = {-# SCC "SimplTopBinds" #-} simplTopBinds simpl_env tagged_binds ; fam_envs = (eps_fam_inst_env eps, fam_inst_env) } ; @@ -542,8 +395,9 @@ simplifyPgmIO pass@(CoreDoSimplify mode max_iterations switches) -- Stop if nothing happened; don't dump output if isZeroSimplCount counts1 then - return ("Simplifier reached fixed point", iteration_no, total_counts, - guts { mg_binds = binds1, mg_rules = rules1 }) + return ( "Simplifier reached fixed point", iteration_no + , totalise (counts1 : counts_so_far) -- Include "free" ticks + , guts { mg_binds = binds1, mg_rules = rules1 } ) else do { -- Short out indirections -- We do this *after* at least one run of the simplifier @@ -560,13 +414,17 @@ simplifyPgmIO pass@(CoreDoSimplify mode max_iterations switches) -- Loop do_iteration us2 (iteration_no + 1) (counts1:counts_so_far) binds2 rules1 - } } } } + } } } } + | otherwise = panic "do_iteration" where (us1, us2) = splitUniqSupply us -- Remember the counts_so_far are reversed - total_counts = foldr (\c acc -> acc `plusSimplCount` c) - (zeroSimplCount dflags) counts_so_far + totalise :: [SimplCount] -> SimplCount + totalise = foldr (\c acc -> acc `plusSimplCount` c) + (zeroSimplCount dflags) + +simplifyPgmIO _ _ _ _ _ = panic "simplifyPgmIO" ------------------- end_iteration :: DynFlags -> CoreToDo -> Int @@ -740,10 +598,10 @@ makeIndEnv binds add_pair :: (Id,CoreExpr) -> IndEnv -> IndEnv add_pair (exported_id, Var local_id) env | shortMeOut env exported_id local_id = extendVarEnv env local_id exported_id - add_pair (exported_id, rhs) env - = env + add_pair _ env = env ----------------- +shortMeOut :: IndEnv -> Id -> Id -> Bool shortMeOut ind_env exported_id local_id -- The if-then-else stuff is just so I can get a pprTrace to see -- how often I don't get shorting out becuase of IdInfo stuff