X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fmain%2FTidyPgm.lhs;h=b3f1a062273201154972ac63aee90a717e3ed5c7;hp=41d9234137ca01c821f5a3d29132db52106798a6;hb=2c8aabcad1d2f2c469cb8a10afa7b66beeaedd45;hpb=b84ba676034763b3082bbd9405794a4fde499d14 diff --git a/compiler/main/TidyPgm.lhs b/compiler/main/TidyPgm.lhs index 41d9234..b3f1a06 100644 --- a/compiler/main/TidyPgm.lhs +++ b/compiler/main/TidyPgm.lhs @@ -18,8 +18,9 @@ import CoreFVs import CoreTidy import CoreMonad import CoreUtils +import Rules import CoreArity ( exprArity, exprBotStrictness_maybe ) -import Class ( classSelIds ) +import Class ( classAllSelIds ) import VarEnv import VarSet import Var @@ -36,14 +37,16 @@ import TcType import DataCon import TyCon import Module +import Packages( isDllName ) import HscTypes import Maybes -import ErrUtils import UniqSupply import Outputable import FastBool hiding ( fastOr ) import Util +import FastString +import Control.Monad ( when ) import Data.List ( sortBy ) import Data.IORef ( IORef, readIORef, writeIORef ) \end{code} @@ -133,7 +136,7 @@ mkBootModDetails :: HscEnv -> [AvailInfo] -> NameEnv TyThing -> [Instance] -> [FamInstEnv.FamInst] -> IO ModDetails mkBootModDetails hsc_env exports type_env insts fam_insts = do { let dflags = hsc_dflags hsc_env - ; showPass dflags "Tidy [hoot] type env" + ; showPass dflags CoreTidy ; let { insts' = tidyInstances globaliseAndTidyId insts ; dfun_ids = map instanceDFunId insts' @@ -289,8 +292,7 @@ tidyProgram hsc_env (ModGuts { mg_module = mod, mg_exports = exports, mg_binds = binds, mg_rules = imp_rules, mg_vect_info = vect_info, - mg_dir_imps = dir_imps, - mg_anns = anns, + mg_anns = anns, mg_deps = deps, mg_foreign = foreign_stubs, mg_hpc_info = hpc_info, @@ -299,9 +301,9 @@ tidyProgram hsc_env (ModGuts { mg_module = mod, mg_exports = exports, = do { let { dflags = hsc_dflags hsc_env ; omit_prags = dopt Opt_OmitInterfacePragmas dflags ; expose_all = dopt Opt_ExposeAllUnfoldings dflags - ; th = dopt Opt_TemplateHaskell dflags + ; th = xopt Opt_TemplateHaskell dflags } - ; showPass dflags "Tidy Core" + ; showPass dflags CoreTidy ; let { implicit_binds = getImplicitBinds type_env } @@ -342,14 +344,28 @@ tidyProgram hsc_env (ModGuts { mg_module = mod, mg_exports = exports, ; alg_tycons = filter isAlgTyCon (typeEnvTyCons type_env) } - ; endPass dflags "Tidy Core" Opt_D_dump_simpl all_tidy_binds tidy_rules - ; let dir_imp_mods = moduleEnvKeys dir_imps - - ; return (CgGuts { cg_module = mod, - cg_tycons = alg_tycons, - cg_binds = all_tidy_binds, - cg_dir_imps = dir_imp_mods, - cg_foreign = foreign_stubs, + ; endPass dflags CoreTidy all_tidy_binds tidy_rules + + -- If the endPass didn't print the rules, but ddump-rules is on, print now + ; dumpIfSet (dopt Opt_D_dump_rules dflags + && (not (dopt Opt_D_dump_simpl dflags))) + CoreTidy + (ptext (sLit "rules")) + (pprRulesForUser tidy_rules) + + -- Print one-line size info + ; let cs = coreBindsStats tidy_binds + ; when (dopt Opt_D_dump_core_stats dflags) + (printDump (ptext (sLit "Tidy size (terms,types,coercions)") + <+> ppr (moduleName mod) <> colon + <+> int (cs_tm cs) + <+> int (cs_ty cs) + <+> int (cs_co cs) )) + + ; return (CgGuts { cg_module = mod, + cg_tycons = alg_tycons, + cg_binds = all_tidy_binds, + cg_foreign = foreign_stubs, cg_dep_pkgs = dep_pkgs deps, cg_hpc_info = hpc_info, cg_modBreaks = modBreaks }, @@ -445,7 +461,7 @@ mustExposeTyCon exports tc | isEnumerationTyCon tc -- For an enumeration, exposing the constructors = True -- won't lead to the need for further exposure -- (This includes data types with no constructors.) - | isOpenTyCon tc -- Open type family + | isFamilyTyCon tc -- Open type family = True | otherwise -- Newtype, datatype @@ -471,12 +487,16 @@ tidyInstances tidy_dfun ispecs \begin{code} tidyVectInfo :: TidyEnv -> VectInfo -> VectInfo -tidyVectInfo (_, var_env) info@(VectInfo { vectInfoVar = vars - , vectInfoPADFun = pas - , vectInfoIso = isos }) - = info { vectInfoVar = tidy_vars - , vectInfoPADFun = tidy_pas - , vectInfoIso = tidy_isos } +tidyVectInfo (_, var_env) info@(VectInfo { vectInfoVar = vars + , vectInfoPADFun = pas + , vectInfoIso = isos + , vectInfoScalarVars = scalarVars + }) + = info { vectInfoVar = tidy_vars + , vectInfoPADFun = tidy_pas + , vectInfoIso = tidy_isos + , vectInfoScalarVars = tidy_scalarVars + } where tidy_vars = mkVarEnv $ map tidy_var_mapping @@ -488,6 +508,10 @@ tidyVectInfo (_, var_env) info@(VectInfo { vectInfoVar = vars tidy_var_mapping (from, to) = (from', (from', lookup_var to)) where from' = lookup_var from tidy_snd_var (x, var) = (x, lookup_var var) + + tidy_scalarVars = mkVarSet + $ map lookup_var + $ varSetElems scalarVars lookup_var var = lookupWithDefaultVarEnv var_env var var \end{code} @@ -551,7 +575,7 @@ getImplicitBinds type_env = map get_defn (concatMap implicit_ids (typeEnvElts type_env)) where implicit_ids (ATyCon tc) = mapCatMaybes dataConWrapId_maybe (tyConDataCons tc) - implicit_ids (AClass cls) = classSelIds cls + implicit_ids (AClass cls) = classAllSelIds cls implicit_ids _ = [] get_defn :: Id -> CoreBind @@ -686,7 +710,7 @@ addExternal expose_all id = (new_needed_ids, show_unfold) (varSetElems spec_ids) -- XXX non-det ordering idinfo = idInfo id - dont_inline = isNeverActive (inlinePragmaActivation (inlinePragInfo idinfo)) + never_active = isNeverActive (inlinePragmaActivation (inlinePragInfo idinfo)) loop_breaker = isNonRuleLoopBreaker (occInfo idinfo) bottoming_fn = isBottomingSig (strictnessInfo idinfo `orElse` topSig) spec_ids = specInfoFreeVars (specInfo idinfo) @@ -699,16 +723,30 @@ addExternal expose_all id = (new_needed_ids, show_unfold) mb_unfold_ids :: Maybe (IdSet, [Id]) -- Nothing => don't unfold mb_unfold_ids = case unfoldingInfo idinfo of - CoreUnfolding { uf_tmpl = unf_rhs, uf_guidance = guide } - | expose_all || -- expose_all says to expose all - -- unfoldings willy-nilly - not (bottoming_fn -- No need to inline bottom functions - || dont_inline -- Or ones that say not to - || loop_breaker -- Or that are loop breakers - || neverUnfoldGuidance guide) - -> Just (exprFvsInOrder unf_rhs) - DFunUnfolding _ ops -> Just (exprsFvsInOrder ops) - _ -> Nothing + CoreUnfolding { uf_tmpl = unf_rhs, uf_src = src, uf_guidance = guide } + | show_unfolding src guide + -> Just (unf_ext_ids src unf_rhs) + DFunUnfolding _ _ ops -> Just (exprsFvsInOrder (dfunArgExprs ops)) + _ -> Nothing + where + unf_ext_ids (InlineWrapper v) _ = (unitVarSet v, [v]) + unf_ext_ids _ unf_rhs = exprFvsInOrder unf_rhs + -- For a wrapper, externalise the wrapper id rather than the + -- fvs of the rhs. The two usually come down to the same thing + -- but I've seen cases where we had a wrapper id $w but a + -- rhs where $w had been inlined; see Trac #3922 + + show_unfolding unf_source unf_guidance + = expose_all -- 'expose_all' says to expose all + -- unfoldings willy-nilly + + || isStableSource unf_source -- Always expose things whose + -- source is an inline rule + + || not (bottoming_fn -- No need to inline bottom functions + || never_active -- Or ones that say not to + || loop_breaker -- Or that are loop breakers + || neverUnfoldGuidance unf_guidance) -- We want a deterministic free-variable list. exprFreeVars gives us -- a VarSet, which is in a non-deterministic order when converted to a @@ -830,10 +868,9 @@ tidyTopName mod nc_var maybe_ref occ_env id (occ_env', occ') = tidyOccName occ_env new_occ - mk_new_local nc = (nc { nsUniqs = us2 }, mkInternalName uniq occ' loc) + mk_new_local nc = (nc { nsUniqs = us }, mkInternalName uniq occ' loc) where - (us1, us2) = splitUniqSupply (nsUniqs nc) - uniq = uniqFromSupply us1 + (uniq, us) = takeUniqFromSupply (nsUniqs nc) mk_new_external nc = allocateGlobalBinder nc mod occ' loc -- If we want to externalise a currently-local name, check @@ -976,54 +1013,14 @@ tidyTopPair :: Bool -- show unfolding -- in the IdInfo of one early in the group tidyTopPair show_unfold rhs_tidy_env caf_info name' (bndr, rhs) - = WARN( not _bottom_exposed, ppr bndr1 ) - (bndr1, rhs1) + = (bndr1, rhs1) where - -- If the cheap-and-cheerful bottom analyser can see that - -- the RHS is bottom, it should jolly well be exposed - _bottom_exposed = case exprBotStrictness_maybe rhs of - Nothing -> True - Just (arity, _) -> appIsBottom str_sig arity - where - - bndr1 = mkGlobalId details name' ty' idinfo' details = idDetails bndr -- Preserve the IdDetails ty' = tidyTopType (idType bndr) rhs1 = tidyExpr rhs_tidy_env rhs - idinfo = idInfo bndr - unf_info = unfoldingInfo idinfo - str_sig = strictnessInfo idinfo `orElse` topSig - is_bot = isBottomingSig str_sig - idinfo' = tidyTopIdInfo (isExternalName name') - idinfo unfold_info - arity caf_info - (occInfo idinfo) - - unfold_info | show_unfold = tidyUnfolding rhs_tidy_env rhs1 is_bot unf_info - | otherwise = noUnfolding - -- NB: do *not* expose the worker if show_unfold is off, - -- because that means this thing is a loop breaker or - -- marked NOINLINE or something like that - -- This is important: if you expose the worker for a loop-breaker - -- then you can make the simplifier go into an infinite loop, because - -- in effect the unfolding is exposed. See Trac #1709 - -- - -- You might think that if show_unfold is False, then the thing should - -- not be w/w'd in the first place. But a legitimate reason is this: - -- the function returns bottom - -- In this case, show_unfold will be false (we don't expose unfoldings - -- for bottoming functions), but we might still have a worker/wrapper - -- split (see Note [Worker-wrapper for bottoming functions] in WorkWrap.lhs - - -- Usually the Id will have an accurate arity on it, because - -- the simplifier has just run, but not always. - -- One case I found was when the last thing the simplifier - -- did was to let-bind a non-atomic argument and then float - -- it to the top level. So it seems more robust just to - -- fix it here. - arity = exprArity rhs - + idinfo' = tidyTopIdInfo rhs_tidy_env name' rhs rhs1 (idInfo bndr) + show_unfold caf_info -- tidyTopIdInfo creates the final IdInfo for top-level -- binders. There are two delicate pieces: @@ -1037,52 +1034,79 @@ tidyTopPair show_unfold rhs_tidy_env caf_info name' (bndr, rhs) -- occurrences of the binders in RHSs, and hence to occurrences in -- unfoldings, which are inside Ids imported by GHCi. Ditto RULES. -- CoreToStg makes use of this when constructing SRTs. -tidyTopIdInfo :: Bool -> IdInfo -> Unfolding - -> ArityInfo -> CafInfo -> OccInfo - -> IdInfo -tidyTopIdInfo is_external idinfo unfold_info arity caf_info occ_info +tidyTopIdInfo :: TidyEnv -> Name -> CoreExpr -> CoreExpr + -> IdInfo -> Bool -> CafInfo -> IdInfo +tidyTopIdInfo rhs_tidy_env name orig_rhs tidy_rhs idinfo show_unfold caf_info | not is_external -- For internal Ids (not externally visible) = vanillaIdInfo -- we only need enough info for code generation -- Arity and strictness info are enough; -- c.f. CoreTidy.tidyLetBndr - `setOccInfo` robust_occ_info - `setCafInfo` caf_info - `setArityInfo` arity - `setStrictnessInfo` strictnessInfo idinfo + `setCafInfo` caf_info + `setArityInfo` arity + `setStrictnessInfo` final_sig | otherwise -- Externally-visible Ids get the whole lot = vanillaIdInfo - `setOccInfo` robust_occ_info `setCafInfo` caf_info `setArityInfo` arity - `setStrictnessInfo` strictnessInfo idinfo - `setInlinePragInfo` inlinePragInfo idinfo + `setStrictnessInfo` final_sig + `setOccInfo` robust_occ_info + `setInlinePragInfo` (inlinePragInfo idinfo) `setUnfoldingInfo` unfold_info -- NB: we throw away the Rules -- They have already been extracted by findExternalRules where - robust_occ_info = zapFragileOcc occ_info + is_external = isExternalName name + + --------- OccInfo ------------ + robust_occ_info = zapFragileOcc (occInfo idinfo) -- It's important to keep loop-breaker information -- when we are doing -fexpose-all-unfoldings + --------- Strictness ------------ + final_sig | Just sig <- strictnessInfo idinfo + = WARN( _bottom_hidden sig, ppr name ) Just sig + | Just (_, sig) <- mb_bot_str = Just sig + | otherwise = Nothing + -- If the cheap-and-cheerful bottom analyser can see that + -- the RHS is bottom, it should jolly well be exposed + _bottom_hidden id_sig = case mb_bot_str of + Nothing -> False + Just (arity, _) -> not (appIsBottom id_sig arity) ------------- Unfolding -------------- -tidyUnfolding :: TidyEnv -> CoreExpr -> Bool -> Unfolding -> Unfolding -tidyUnfolding tidy_env _ _ (DFunUnfolding con ids) - = DFunUnfolding con (map (tidyExpr tidy_env) ids) -tidyUnfolding tidy_env tidy_rhs is_bottoming - unf@(CoreUnfolding { uf_tmpl = unf_rhs, uf_src = src }) - | isInlineRuleSource src - = unf { uf_tmpl = tidyExpr tidy_env unf_rhs, -- Preserves OccInfo - uf_src = tidyInl tidy_env src } - | otherwise - = mkTopUnfolding is_bottoming tidy_rhs -tidyUnfolding _ _ _ unf = unf + mb_bot_str = exprBotStrictness_maybe orig_rhs -tidyInl :: TidyEnv -> UnfoldingSource -> UnfoldingSource -tidyInl tidy_env (InlineWrapper w) = InlineWrapper (tidyVarOcc tidy_env w) -tidyInl _ inl_info = inl_info + --------- Unfolding ------------ + unf_info = unfoldingInfo idinfo + unfold_info | show_unfold = tidyUnfolding rhs_tidy_env unf_info unf_from_rhs + | otherwise = noUnfolding + unf_from_rhs = mkTopUnfolding is_bot tidy_rhs + is_bot = case final_sig of + Just sig -> isBottomingSig sig + Nothing -> False + -- NB: do *not* expose the worker if show_unfold is off, + -- because that means this thing is a loop breaker or + -- marked NOINLINE or something like that + -- This is important: if you expose the worker for a loop-breaker + -- then you can make the simplifier go into an infinite loop, because + -- in effect the unfolding is exposed. See Trac #1709 + -- + -- You might think that if show_unfold is False, then the thing should + -- not be w/w'd in the first place. But a legitimate reason is this: + -- the function returns bottom + -- In this case, show_unfold will be false (we don't expose unfoldings + -- for bottoming functions), but we might still have a worker/wrapper + -- split (see Note [Worker-wrapper for bottoming functions] in WorkWrap.lhs + + --------- Arity ------------ + -- Usually the Id will have an accurate arity on it, because + -- the simplifier has just run, but not always. + -- One case I found was when the last thing the simplifier + -- did was to let-bind a non-atomic argument and then float + -- it to the top level. So it seems more robust just to + -- fix it here. + arity = exprArity orig_rhs \end{code} %************************************************************************ @@ -1109,12 +1133,12 @@ CAF list to keep track of non-collectable CAFs. \begin{code} hasCafRefs :: PackageId -> VarEnv Var -> Arity -> CoreExpr -> CafInfo hasCafRefs this_pkg p arity expr - | is_caf || mentions_cafs - = MayHaveCafRefs + | is_caf || mentions_cafs = MayHaveCafRefs | otherwise = NoCafRefs where mentions_cafs = isFastTrue (cafRefs p expr) - is_caf = not (arity > 0 || rhsIsStatic this_pkg expr) + is_dynamic_name = isDllName this_pkg + is_caf = not (arity > 0 || rhsIsStatic is_dynamic_name expr) -- NB. we pass in the arity of the expression, which is expected -- to be calculated by exprArity. This is because exprArity @@ -1140,6 +1164,7 @@ cafRefs p (Case e _bndr _ alts) = fastOr (cafRefs p e) (cafRefss p) (rhssOfAlts cafRefs p (Note _n e) = cafRefs p e cafRefs p (Cast e _co) = cafRefs p e cafRefs _ (Type _) = fastBool False +cafRefs _ (Coercion _) = fastBool False cafRefss :: VarEnv Id -> [Expr a] -> FastBool cafRefss _ [] = fastBool False