From 72a9e0e26358e02dec63453d55fbc24a6f13f789 Mon Sep 17 00:00:00 2001 From: simonpj <unknown> Date: Tue, 14 Apr 1998 14:00:06 +0000 Subject: [PATCH] [project @ 1998-04-14 13:59:59 by simonpj] Finally replace Specialise.dictRhsFVs with a proper free-variable finder, FreeVars.exprFreeVars --- ghc/compiler/coreSyn/FreeVars.lhs | 257 +++++++------------------ ghc/compiler/main/MkIface.lhs | 9 +- ghc/compiler/specialise/Specialise.lhs | 27 +-- 3 files changed, 74 insertions(+), 219 deletions(-) diff --git a/ghc/compiler/coreSyn/FreeVars.lhs b/ghc/compiler/coreSyn/FreeVars.lhs index cba706971c9e..48185a984bcd 100644 --- a/ghc/compiler/coreSyn/FreeVars.lhs +++ b/ghc/compiler/coreSyn/FreeVars.lhs @@ -5,16 +5,14 @@ Taken quite directly from the Peyton Jones/Lester paper. \begin{code} module FreeVars ( - freeVars, - - -- cheap and cheerful variant... - addTopBindsFVs, addExprFVs, + -- Cheap and cheerful variant... + exprFreeVars, + -- Complicated and expensive variant for float-out + freeVars, freeVarsOf, freeTyVarsOf, - FVCoreExpr, FVCoreBinding, - CoreExprWithFVs, -- For the above functions - AnnCoreExpr, -- Dito + AnnCoreExpr, -- Dito FVInfo(..), LeakInfo(..) ) where @@ -36,7 +34,7 @@ import TyVar ( emptyTyVarSet, unitTyVarSet, minusTyVarSet, TyVarSet, TyVar ) import BasicTypes ( Unused ) -import UniqSet ( unionUniqSets ) +import UniqSet ( unionUniqSets, addOneToUniqSet ) import Util ( panic, assertPanic ) \end{code} @@ -77,6 +75,7 @@ aFreeTyVar t = unitTyVarSet t is_among = elementOfIdSet munge_id_ty i = tyVarsOfType (idType i) combine = unionUniqSets -- used both for {Id,TyVar}Sets +add = addOneToUniqSet combineFVInfo (FVInfo fvs1 tfvs1 leak1) (FVInfo fvs2 tfvs2 leak2) = FVInfo (fvs1 `combine` fvs2) @@ -344,213 +343,91 @@ leakinessOf (FVInfo _ _ leakiness, _) = leakiness %************************************************************************ %* * -\section[freevars-binders]{Attaching free variables to binders +\section{Finding the free variables of an expression} %* * %************************************************************************ - -Here's an variant of the free-variable pass, which pins free-variable -information on {\em binders} rather than every single jolly -expression! -\begin{itemize} -\item - The free vars attached to a lambda binder are the free vars of the - whole lambda abstraction. If there are multiple binders, they are - each given the same free-var set. -\item - The free vars attached to a let(rec) binder are the free vars of the - rhs of the binding. In the case of letrecs, this set excludes the - binders themselves. -\item - The free vars attached to a case alternative binder are the free - vars of the alternative, excluding the alternative's binders. -\end{itemize} - -There's a predicate carried in which tells what is a free-var -candidate. It is passed the Id and a set of in-scope Ids. - -(Global) constructors used on the rhs in a Con are also treated as -potential free-var candidates (though they will not be recorded in the -in-scope set). The predicate must decide if they are to be recorded as -free-vars. - -As it happens this is only ever used by the Specialiser! +This function simply finds the free variables of an expression. \begin{code} -type FVCoreBinder = (Id, IdSet) -type FVCoreExpr = GenCoreExpr FVCoreBinder Id Unused -type FVCoreBinding = GenCoreBinding FVCoreBinder Id Unused - type InterestingIdFun - = IdSet -- Non-top-level in-scope variables - -> Id -- The Id being looked at + = Id -- The Id being looked at -> Bool -- True <=> interesting -\end{code} - -\begin{code} -addExprFVs :: InterestingIdFun -- "Interesting id" predicate - -> IdSet -- In scope ids - -> CoreExpr - -> (FVCoreExpr, IdSet) -addExprFVs fv_cand in_scope (Var v) - = (Var v, if fv_cand in_scope v - then aFreeId v - else noFreeIds) - -addExprFVs fv_cand in_scope (Lit lit) = (Lit lit, noFreeIds) - -addExprFVs fv_cand in_scope (Con con args) - = (Con con args, - if fv_cand in_scope con - then aFreeId con - else noFreeIds `combine` fvsOfArgs fv_cand in_scope args) - -addExprFVs fv_cand in_scope (Prim op args) - = (Prim op args, fvsOfArgs fv_cand in_scope args) +exprFreeVars :: InterestingIdFun -> CoreExpr -> IdSet +exprFreeVars fv_cand e = expr_fvs fv_cand emptyIdSet e +\end{code} -addExprFVs fv_cand in_scope (Lam binder body) - = (Lam new_binder new_body, lam_fvs) - where - (new_binder, binder_set) - = case binder of - TyBinder t -> (TyBinder t, emptyIdSet) - ValBinder b -> (ValBinder (b, lam_fvs), - unitIdSet b) - - new_in_scope = in_scope `combine` binder_set - (new_body, body_fvs) = addExprFVs fv_cand new_in_scope body - lam_fvs = body_fvs `minusIdSet` binder_set - -addExprFVs fv_cand in_scope (App fun arg) - = (App fun2 arg, fun_fvs `combine` fvsOfArgs fv_cand in_scope [arg]) - where - (fun2, fun_fvs) = addExprFVs fv_cand in_scope fun -addExprFVs fv_cand in_scope (Case scrut alts) - = (Case scrut' alts', scrut_fvs `combine` alts_fvs) +\begin{code} +expr_fvs :: InterestingIdFun -- "Interesting id" predicate + -> IdSet -- In scope ids + -> CoreExpr + -> IdSet + +expr_fvs fv_cand in_scope (Var v) = id_fvs fv_cand in_scope v +expr_fvs fv_cand in_scope (Lit lit) = noFreeIds +expr_fvs fv_cand in_scope (Con con args) = args_fvs fv_cand in_scope args +expr_fvs fv_cand in_scope (Prim op args) = args_fvs fv_cand in_scope args +expr_fvs fv_cand in_scope (Note _ expr) = expr_fvs fv_cand in_scope expr +expr_fvs fv_cand in_scope (App fun arg) = expr_fvs fv_cand in_scope fun `combine` + arg_fvs fv_cand in_scope arg + + +expr_fvs fv_cand in_scope (Lam (ValBinder b) body) + = (expr_fvs fv_cand (in_scope `add` b) body) +expr_fvs fv_cand in_scope (Lam (TyBinder b) body) + = expr_fvs fv_cand in_scope body + +expr_fvs fv_cand in_scope (Case scrut alts) + = expr_fvs fv_cand in_scope scrut `combine` alts_fvs where - (scrut', scrut_fvs) = addExprFVs fv_cand in_scope scrut - - (alts', alts_fvs) + alts_fvs = case alts of - AlgAlts alg_alts deflt -> (AlgAlts alg_alts' deflt', fvs) + AlgAlts alg_alts deflt -> unionManyIdSets (deflt_fvs : alt_fvs) where - (alg_alts', alt_fvs) = unzip (map do_alg_alt alg_alts) - (deflt', deflt_fvs) = do_deflt deflt - fvs = unionManyIdSets (deflt_fvs : alt_fvs) + alt_fvs = map do_alg_alt alg_alts + deflt_fvs = do_deflt deflt - PrimAlts prim_alts deflt -> (PrimAlts prim_alts' deflt', fvs) + PrimAlts prim_alts deflt -> unionManyIdSets (deflt_fvs : alt_fvs) where - (prim_alts', alt_fvs) = unzip (map do_prim_alt prim_alts) - (deflt', deflt_fvs) = do_deflt deflt - fvs = unionManyIdSets (deflt_fvs : alt_fvs) + alt_fvs = map do_prim_alt prim_alts + deflt_fvs = do_deflt deflt - do_alg_alt :: (Id, [Id], CoreExpr) - -> ((Id, [FVCoreBinder], FVCoreExpr), IdSet) - - do_alg_alt (con, args, rhs) = ((con, args `zip` (repeat fvs), rhs'), fvs) + do_alg_alt :: (Id, [Id], CoreExpr) -> IdSet + do_alg_alt (con, args, rhs) = expr_fvs fv_cand new_in_scope rhs where - new_in_scope = in_scope `combine` arg_set - (rhs', rhs_fvs) = addExprFVs fv_cand new_in_scope rhs - fvs = rhs_fvs `minusIdSet` arg_set - arg_set = mkIdSet args + new_in_scope = in_scope `combine` mkIdSet args - do_prim_alt (lit, rhs) = ((lit, rhs'), rhs_fvs) - where - (rhs', rhs_fvs) = addExprFVs fv_cand in_scope rhs + do_prim_alt (lit, rhs) = expr_fvs fv_cand in_scope rhs - do_deflt NoDefault = (NoDefault, noFreeIds) - do_deflt (BindDefault var rhs) - = (BindDefault (var,fvs) rhs', fvs) - where - new_in_scope = in_scope `combine` var_set - (rhs', rhs_fvs) = addExprFVs fv_cand new_in_scope rhs - fvs = rhs_fvs `minusIdSet` var_set - var_set = aFreeId var + do_deflt NoDefault = noFreeIds + do_deflt (BindDefault b rhs) = expr_fvs fv_cand (in_scope `add` b) rhs + +expr_fvs fv_cand in_scope (Let (NonRec b r) body) + = expr_fvs fv_cand in_scope r `combine` + expr_fvs fv_cand (in_scope `add` b) body -addExprFVs fv_cand in_scope (Let binds body) - = (Let binds' body2, fvs_binds `combine` (fvs_body `minusIdSet` binder_set)) +expr_fvs fv_cand in_scope (Let (Rec pairs) body) + = foldr (combine . expr_fvs fv_cand in_scope' . snd) noFreeIds pairs `combine` + expr_fvs fv_cand in_scope' body where - (binds', fvs_binds, new_in_scope, binder_set) - = addBindingFVs fv_cand in_scope binds + in_scope' = in_scope `combine` mkIdSet (map fst pairs) - (body2, fvs_body) = addExprFVs fv_cand new_in_scope body -addExprFVs fv_cand in_scope (Note note expr) - = (Note note expr2, expr_fvs) - where - (expr2, expr_fvs) = addExprFVs fv_cand in_scope expr -\end{code} -\begin{code} -addBindingFVs - :: InterestingIdFun -- "Interesting id" predicate - -> IdSet -- In scope ids - -> CoreBinding - -> (FVCoreBinding, - IdSet, -- Free vars of binding group - IdSet, -- Augmented in-scope Ids - IdSet) -- Set of Ids bound by this binding - -addBindingFVs fv_cand in_scope (NonRec binder rhs) - = (NonRec binder' rhs', fvs, new_in_scope, binder_set) - where - ((binder', rhs'), fvs) = do_pair fv_cand in_scope binder_set (binder, rhs) - new_in_scope = in_scope `combine` binder_set - binder_set = aFreeId binder -addBindingFVs fv_cand in_scope (Rec pairs) - = (Rec pairs', unionManyIdSets fvs_s, new_in_scope, binder_set) - where - binders = [binder | (binder,_) <- pairs] - binder_set = mkIdSet binders - new_in_scope = in_scope `combine` binder_set - (pairs', fvs_s) = unzip (map (do_pair fv_cand new_in_scope binder_set) pairs) -\end{code} +-------------------------------------- +arg_fvs fv_cand in_scope (VarArg v) = id_fvs fv_cand in_scope v +arg_fvs fv_cand in_scope other_arg = noFreeIds -\begin{code} -addTopBindsFVs - :: InterestingIdFun -- "Interesting id" predicate - -> [CoreBinding] - -> ([FVCoreBinding], - IdSet) - -addTopBindsFVs fv_cand [] = ([], noFreeIds) -addTopBindsFVs fv_cand (b:bs) - = let - (b', fvs_b, _, _) = addBindingFVs fv_cand noFreeIds b - (bs', fvs_bs) = addTopBindsFVs fv_cand bs - in - (b' : bs', fvs_b `combine` fvs_bs) -\end{code} +-------------------------------------- +args_fvs fv_cand in_scope args = foldr (combine . arg_fvs fv_cand in_scope) noFreeIds args -\begin{code} -fvsOfArgs :: InterestingIdFun -- "Interesting id" predicate - -> IdSet -- In scope ids - -> [CoreArg] - -> IdSet - -fvsOfArgs _ _ [] = noFreeIds - -fvsOfArgs fv_cand in_scope [VarArg v] -- this is only a short-cut... - = if (fv_cand in_scope v) then aFreeId v else noFreeIds -fvsOfArgs _ _ [ _ ] = noFreeIds - -fvsOfArgs fv_cand in_scope args - = mkIdSet [ v | (VarArg v) <- args, fv_cand in_scope v ] - -- all other types of args are uninteresting here... - ----------- -do_pair :: InterestingIdFun -- "Interesting id" predicate - -> IdSet -- In scope ids - -> IdSet - -> (Id, CoreExpr) - -> ((FVCoreBinder, FVCoreExpr), IdSet) - -do_pair fv_cand in_scope binder_set (binder,rhs) - = (((binder, fvs), rhs'), fvs) - where - (rhs', rhs_fvs) = addExprFVs fv_cand in_scope rhs - fvs = rhs_fvs `minusIdSet` binder_set + +-------------------------------------- +id_fvs fv_cand in_scope v + | v `elementOfIdSet` in_scope = noFreeIds + | fv_cand v = aFreeId v + | otherwise = noFreeIds \end{code} diff --git a/ghc/compiler/main/MkIface.lhs b/ghc/compiler/main/MkIface.lhs index e3648e723cf1..fd6d8c89bc91 100644 --- a/ghc/compiler/main/MkIface.lhs +++ b/ghc/compiler/main/MkIface.lhs @@ -42,7 +42,7 @@ import IdInfo ( IdInfo, StrictnessInfo, ArityInfo, InlinePragInfo(..), inlinePr ) import CoreSyn ( CoreExpr, CoreBinding, GenCoreExpr, GenCoreBinding(..) ) import CoreUnfold ( calcUnfoldingGuidance, UnfoldingGuidance(..), Unfolding ) -import FreeVars ( addExprFVs ) +import FreeVars ( exprFreeVars ) import Name ( isLocallyDefined, isWiredInName, modAndOcc, nameModule, pprOccName, OccName, occNameString, nameOccName, nameString, isExported, Name {-instance NamedThing-}, Provenance, NamedThing(..) @@ -346,10 +346,9 @@ ifaceId get_idinfo needed_ids is_rec id rhs find_fvs expr = free_vars where - (_,free_vars) = addExprFVs interesting emptyIdSet expr - interesting bound id = isLocallyDefined id && - not (id `elementOfIdSet` bound) && - not (omitIfaceSigForId id) + free_vars = exprFreeVars interesting expr + interesting id = isLocallyDefined id && + not (omitIfaceSigForId id) \end{code} \begin{code} diff --git a/ghc/compiler/specialise/Specialise.lhs b/ghc/compiler/specialise/Specialise.lhs index 04cd693c85b0..5e7ca37c5b42 100644 --- a/ghc/compiler/specialise/Specialise.lhs +++ b/ghc/compiler/specialise/Specialise.lhs @@ -34,8 +34,9 @@ import TyVar ( TyVar, mkTyVar, ) import Kind ( mkBoxedTypeKind ) import CoreSyn +import FreeVars ( exprFreeVars ) import PprCore () -- Instances -import Name ( NamedThing(..), getSrcLoc, mkSysLocalName ) +import Name ( NamedThing(..), getSrcLoc, mkSysLocalName, isLocallyDefined ) import SrcLoc ( noSrcLoc ) import SpecEnv ( addToSpecEnv, lookupSpecEnv, specEnvValues ) @@ -1096,29 +1097,7 @@ lookupId env id = case lookupIdEnv env id of Just id' -> id' dictRhsFVs :: CoreExpr -> IdSet - -- Cheapo function for simple RHSs -dictRhsFVs e - = go e - where - go (App e1 (VarArg a)) = go e1 `addOneToIdSet` a - go (App e1 (LitArg l)) = go e1 - go (App e1 (TyArg t)) = go e1 - go (Var v) = unitIdSet v - go (Lit l) = emptyIdSet - go (Con _ args) = mkIdSet [id | VarArg id <- args] - go (Note _ e) = go e - - go (Case e _) = go e -- Claim: no free dictionaries in the alternatives - -- These case expressions are of the form - -- case d of { D a b c -> b } - - go (Lam _ _) = emptyIdSet -- This can happen for a Functor "dict", - -- which is represented by the function - -- itself; but it won't have any further - -- dicts inside it. I hope. - - go other = pprPanic "dictRhsFVs" (ppr e) - +dictRhsFVs e = exprFreeVars isLocallyDefined e addIdSpecialisations id spec_stuff = (if not (null errs) then -- GitLab