X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2FsimplCore%2FSimplCore.lhs;h=95bd40b331f233fa8894be652e2d2f08ed51d6a6;hb=318c22aad1837e471cbf59c6fddd6987a36c2c9b;hp=c7b2e6919f69e02c54c1b23dd1efc7b2e0832202;hpb=609db9ce4ad70c8cf64350b75da03229a7c33b0f;p=ghc-hetmet.git diff --git a/compiler/simplCore/SimplCore.lhs b/compiler/simplCore/SimplCore.lhs index c7b2e69..95bd40b 100644 --- a/compiler/simplCore/SimplCore.lhs +++ b/compiler/simplCore/SimplCore.lhs @@ -17,11 +17,9 @@ module SimplCore ( core2core, simplifyExpr ) where import DynFlags ( CoreToDo(..), SimplifierSwitch(..), SimplifierMode(..), DynFlags, DynFlag(..), dopt, - getCoreToDo ) + getCoreToDo, shouldDumpSimplPhase ) import CoreSyn -import HscTypes ( HscEnv(..), ModGuts(..), ExternalPackageState(..), - Dependencies( dep_mods ), - hscEPS, hptRules ) +import HscTypes import CSE ( cseProgram ) import Rules ( RuleBase, emptyRuleBase, mkRuleBase, unionRuleBase, extendRuleBaseList, pprRuleBase, ruleCheckProgram, @@ -37,12 +35,14 @@ import Simplify ( simplTopBinds, simplExpr ) import SimplEnv ( SimplEnv, simplBinders, mkSimplEnv, setInScopeSet ) import SimplMonad import ErrUtils ( dumpIfSet, dumpIfSet_dyn, showPass ) -import CoreLint ( endPass, endIteration ) +import CoreLint ( endPassIf, endIteration ) import FloatIn ( floatInwards ) import FloatOut ( floatOutwards ) import FamInstEnv -import Id ( Id, modifyIdInfo, idInfo, isExportedId, isLocalId, - idSpecialisation, idName ) +import Id +import DataCon +import TyCon ( tyConSelIds, tyConDataCons ) +import Class ( classSelIds ) import VarSet import VarEnv import NameEnv ( lookupNameEnv ) @@ -57,12 +57,14 @@ import StrictAnal ( saBinds ) import CprAnalyse ( cprAnalyse ) #endif import Vectorise ( vectorise ) +import Util import UniqSupply ( UniqSupply, mkSplitUniqSupply, splitUniqSupply ) import IO ( hPutStr, stderr ) import Outputable -import List ( partition ) -import Maybes ( orElse ) +import Control.Monad +import List ( partition, intersperse ) +import Maybes \end{code} %************************************************************************ @@ -77,26 +79,30 @@ core2core :: HscEnv -> IO ModGuts core2core hsc_env guts - = do - let dflags = hsc_dflags hsc_env - core_todos = getCoreToDo dflags + = do { + ; let dflags = hsc_dflags hsc_env + core_todos = getCoreToDo dflags - us <- mkSplitUniqSupply 's' - let (cp_us, ru_us) = splitUniqSupply us + ; us <- mkSplitUniqSupply 's' + ; let (cp_us, ru_us) = splitUniqSupply us -- COMPUTE THE RULE BASE TO USE - (imp_rule_base, guts') <- prepareRules hsc_env guts ru_us + ; (imp_rule_base, guts1) <- prepareRules hsc_env guts ru_us + + -- Note [Injecting implicit bindings] + ; let implicit_binds = getImplicitBinds (mg_types guts1) + guts2 = guts1 { mg_binds = implicit_binds ++ mg_binds guts1 } -- DO THE BUSINESS - (stats, guts'') <- doCorePasses hsc_env imp_rule_base cp_us - (zeroSimplCount dflags) - guts' core_todos + ; (stats, guts3) <- doCorePasses hsc_env imp_rule_base cp_us + (zeroSimplCount dflags) + guts2 core_todos - dumpIfSet_dyn dflags Opt_D_dump_simpl_stats + ; dumpIfSet_dyn dflags Opt_D_dump_simpl_stats "Grand total simplifier statistics" (pprSimplCount stats) - return guts'' + ; return guts3 } simplifyExpr :: DynFlags -- includes spec of what core-to-core passes to do @@ -212,10 +218,51 @@ observe do_pass hsc_env us rb guts \end{code} +%************************************************************************ +%* * + Implicit bindings +%* * +%************************************************************************ + +Note [Injecting implicit bindings] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +We used to inject the implict bindings right at the end, in CoreTidy. +But some of these bindings, notably record selectors, are not +constructed in an optimised form. E.g. record selector for + data T = MkT { x :: {-# UNPACK #-} !Int } +Then the unfolding looks like + x = \t. case t of MkT x1 -> let x = I# x1 in x +This generates bad code unless it's first simplified a bit. +(Only matters when the selector is used curried; eg map x ys.) +See Trac #2070. + +\begin{code} +getImplicitBinds :: TypeEnv -> [CoreBind] +getImplicitBinds type_env + = map get_defn (concatMap implicit_con_ids (typeEnvTyCons type_env) + ++ concatMap other_implicit_ids (typeEnvElts type_env)) + -- Put the constructor wrappers first, because + -- other implicit bindings (notably the fromT functions arising + -- from generics) use the constructor wrappers. At least that's + -- what External Core likes + where + implicit_con_ids tc = mapCatMaybes dataConWrapId_maybe (tyConDataCons tc) + + other_implicit_ids (ATyCon tc) = filter (not . isNaughtyRecordSelector) (tyConSelIds tc) + -- The "naughty" ones are not real functions at all + -- They are there just so we can get decent error messages + -- See Note [Naughty record selectors] in MkId.lhs + other_implicit_ids (AClass cl) = classSelIds cl + other_implicit_ids _other = [] + + get_defn :: Id -> CoreBind + get_defn id = NonRec id (unfoldingTemplate (idUnfolding id)) +\end{code} + %************************************************************************ %* * -\subsection{Dealing with rules} + Dealing with rules %* * %************************************************************************ @@ -244,7 +291,7 @@ prepareRules hsc_env@(HscEnv { hsc_dflags = dflags, hsc_HPT = hpt }) local_ids = mkInScopeSet (mkVarSet (bindersOfBinds binds)) env = setInScopeSet gentleSimplEnv local_ids (better_rules,_) = initSmpl dflags emptyRuleBase emptyFamInstEnvs us $ - (mapSmpl (simplRule env) local_rules) + (mapM (simplRule env) local_rules) home_pkg_rules = hptRules hsc_env (dep_mods deps) -- Find the rules for locally-defined Ids; then we can attach them @@ -301,12 +348,12 @@ This doesn't match unless you do eta reduction on the build argument. \begin{code} simplRule env rule@(BuiltinRule {}) - = returnSmpl rule + = return rule simplRule env rule@(Rule { ru_bndrs = bndrs, ru_args = args, ru_rhs = rhs }) - = simplBinders env bndrs `thenSmpl` \ (env, bndrs') -> - mapSmpl (simplExprGently env) args `thenSmpl` \ args' -> - simplExprGently env rhs `thenSmpl` \ rhs' -> - returnSmpl (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 = rhs' }) -- It's important that simplExprGently does eta reduction. -- For example, in a rule like: @@ -333,8 +380,8 @@ simplExprGently :: SimplEnv -> CoreExpr -> SimplM CoreExpr -- and in fact that is so.... but the 'Gently' in simplExprGently doesn't -- enforce that; it just simplifies the expression twice -simplExprGently env expr - = simplExpr env (occurAnalyseExpr expr) `thenSmpl` \ expr1 -> +simplExprGently env expr = do + expr1 <- simplExpr env (occurAnalyseExpr expr) simplExpr env (occurAnalyseExpr expr1) \end{code} @@ -403,22 +450,28 @@ simplifyPgm mode switches hsc_env us imp_rule_base guts (termination_msg, it_count, counts_out, binds') <- do_iteration us 1 (zeroSimplCount dflags) (mg_binds guts) ; - dumpIfSet (dopt Opt_D_verbose_core2core dflags - && dopt Opt_D_dump_simpl_stats dflags) + dumpIfSet (dump_phase && dopt Opt_D_dump_simpl_stats dflags) "Simplifier statistics" (vcat [text termination_msg <+> text "after" <+> ppr it_count <+> text "iterations", text "", pprSimplCount counts_out]); - endPass dflags ("Simplify phase " ++ phase_info ++ " done") Opt_D_dump_simpl_phases binds'; + endPassIf dump_phase dflags + ("Simplify phase " ++ phase_info ++ " done") + Opt_D_dump_simpl_phases binds'; return (counts_out, guts { mg_binds = binds' }) } where dflags = hsc_dflags hsc_env phase_info = case mode of - SimplGently -> "gentle" - SimplPhase n -> show n + SimplGently -> "gentle" + SimplPhase n ss -> shows n + . showString " [" + . showString (concat $ intersperse "," ss) + $ "]" + + dump_phase = shouldDumpSimplPhase dflags mode sw_chkr = isAmongSimpl switches max_iterations = intSwitchSet sw_chkr MaxSimplifierIterations `orElse` 2 @@ -428,17 +481,13 @@ simplifyPgm mode switches hsc_env us imp_rule_base guts -- about to begin, with '1' for the first | iteration_no > max_iterations -- Stop if we've run out of iterations = do { -#ifdef DEBUG - if max_iterations > 2 then - hPutStr stderr ("NOTE: Simplifier still going after " ++ + when (debugIsOn && (max_iterations > 2)) $ + hPutStr stderr ("NOTE: Simplifier still going after " ++ show max_iterations ++ " iterations; bailing out. Size = " ++ show (coreBindsSize binds) ++ "\n" ) - else - return (); -#endif -- Subtract 1 from iteration_no to get the -- number of iterations we actually completed - return ("Simplifier baled out", iteration_no - 1, counts, binds) + ; return ("Simplifier bailed out", iteration_no - 1, counts, binds) } -- Try and force thunks off the binds; significantly reduces