summaryrefslogtreecommitdiff
path: root/compiler/stgSyn/CoreToStg.hs
diff options
context:
space:
mode:
authorSebastian Graf <sebastian.graf@kit.edu>2018-11-19 17:48:44 +0100
committerSebastian Graf <sebastian.graf@kit.edu>2018-11-19 17:48:44 +0100
commit47bbc709cb221e32310c6e28eb2f33acf78488c7 (patch)
tree07326ee259a4b547d4a568e815204b7c1f543567 /compiler/stgSyn/CoreToStg.hs
parentcc615c697b54e3141e7b30b975de0b07dc9b8b29 (diff)
downloadhaskell-47bbc709cb221e32310c6e28eb2f33acf78488c7.tar.gz
Don't track free variables in STG syntax by default
Summary: Currently, `CoreToStg` annotates `StgRhsClosure`s with their set of non-global free variables. This free variable information is only needed in the final code generation step (i.e. `StgCmm.codeGen`), which leads to transformations such as `StgCse` and `StgUnarise` having to maintain this information. This is tiresome and unnecessary, so this patch introduces a trees-to-grow-like approach that only introduces the free variable set into the syntax tree in the code gen pass, along with a free variable analysis on STG terms to generate that information. Fixes #15754. Reviewers: simonpj, osa1, bgamari, simonmar Reviewed By: osa1 Subscribers: rwbarton, carter GHC Trac Issues: #15754 Differential Revision: https://phabricator.haskell.org/D5324
Diffstat (limited to 'compiler/stgSyn/CoreToStg.hs')
-rw-r--r--compiler/stgSyn/CoreToStg.hs295
1 files changed, 86 insertions, 209 deletions
diff --git a/compiler/stgSyn/CoreToStg.hs b/compiler/stgSyn/CoreToStg.hs
index 12940753f9..1b1d4639f2 100644
--- a/compiler/stgSyn/CoreToStg.hs
+++ b/compiler/stgSyn/CoreToStg.hs
@@ -46,11 +46,10 @@ import DynFlags
import ForeignCall
import Demand ( isUsedOnce )
import PrimOp ( PrimCall(..) )
-import UniqFM
import SrcLoc ( mkGeneralSrcSpan )
import Data.List.NonEmpty (nonEmpty, toList)
-import Data.Maybe (isJust, fromMaybe)
+import Data.Maybe (fromMaybe)
import Control.Monad (liftM, ap)
-- Note [Live vs free]
@@ -208,7 +207,7 @@ coreToStg :: DynFlags -> Module -> CoreProgram
coreToStg dflags this_mod pgm
= (pgm', final_ccs)
where
- (_, _, (local_ccs, local_cc_stacks), pgm')
+ (_, (local_ccs, local_cc_stacks), pgm')
= coreTopBindsToStg dflags this_mod emptyVarEnv emptyCollectedCCs pgm
prof = WayProf `elem` ways dflags
@@ -229,45 +228,41 @@ coreTopBindsToStg
-> IdEnv HowBound -- environment for the bindings
-> CollectedCCs
-> CoreProgram
- -> (IdEnv HowBound, FreeVarsInfo, CollectedCCs, [StgTopBinding])
+ -> (IdEnv HowBound, CollectedCCs, [StgTopBinding])
coreTopBindsToStg _ _ env ccs []
- = (env, emptyFVInfo, ccs, [])
+ = (env, ccs, [])
coreTopBindsToStg dflags this_mod env ccs (b:bs)
- = (env2, fvs2, ccs2, b':bs')
+ = (env2, ccs2, b':bs')
where
- -- Notice the mutually-recursive "knot" here:
- -- env accumulates down the list of binds,
- -- fvs accumulates upwards
- (env1, fvs2, ccs1, b' ) =
- coreTopBindToStg dflags this_mod env fvs1 ccs b
- (env2, fvs1, ccs2, bs') =
+ (env1, ccs1, b' ) =
+ coreTopBindToStg dflags this_mod env ccs b
+ (env2, ccs2, bs') =
coreTopBindsToStg dflags this_mod env1 ccs1 bs
coreTopBindToStg
:: DynFlags
-> Module
-> IdEnv HowBound
- -> FreeVarsInfo -- Info about the body
-> CollectedCCs
-> CoreBind
- -> (IdEnv HowBound, FreeVarsInfo, CollectedCCs, StgTopBinding)
+ -> (IdEnv HowBound, CollectedCCs, StgTopBinding)
-coreTopBindToStg _ _ env body_fvs ccs (NonRec id e)
+coreTopBindToStg _ _ env ccs (NonRec id e)
| Just str <- exprIsTickedString_maybe e
-- top-level string literal
-- See Note [CoreSyn top-level string literals] in CoreSyn
= let
env' = extendVarEnv env id how_bound
how_bound = LetBound TopLet 0
- in (env', body_fvs, ccs, StgTopStringLit id str)
+ in (env', ccs, StgTopStringLit id str)
-coreTopBindToStg dflags this_mod env body_fvs ccs (NonRec id rhs)
+coreTopBindToStg dflags this_mod env ccs (NonRec id rhs)
= let
env' = extendVarEnv env id how_bound
how_bound = LetBound TopLet $! manifestArity rhs
- (stg_rhs, fvs', ccs') =
+ (stg_rhs, ccs') =
initCts env $
coreToTopStgRhs dflags ccs this_mod (id,rhs)
@@ -278,9 +273,9 @@ coreTopBindToStg dflags this_mod env body_fvs ccs (NonRec id rhs)
-- as well as 'id', but that led to a black hole
-- where printing the assertion error tripped the
-- assertion again!
- (env', fvs' `unionFVInfo` body_fvs, ccs', bind)
+ (env', ccs', bind)
-coreTopBindToStg dflags this_mod env body_fvs ccs (Rec pairs)
+coreTopBindToStg dflags this_mod env ccs (Rec pairs)
= ASSERT( not (null pairs) )
let
binders = map fst pairs
@@ -289,28 +284,27 @@ coreTopBindToStg dflags this_mod env body_fvs ccs (Rec pairs)
| (b, rhs) <- pairs ]
env' = extendVarEnvList env extra_env'
- -- generate StgTopBindings, accumulate body_fvs and CAF cost centres
- -- created for CAFs
- ((fvs', ccs'), stg_rhss)
+ -- generate StgTopBindings and CAF cost centres created for CAFs
+ (ccs', stg_rhss)
= initCts env' $ do
- mapAccumLM (\(fvs, ccs) rhs -> do
- (rhs', fvs', ccs') <-
+ mapAccumLM (\ccs rhs -> do
+ (rhs', ccs') <-
coreToTopStgRhs dflags ccs this_mod rhs
- return ((fvs' `unionFVInfo` fvs, ccs'), rhs'))
- (body_fvs, ccs)
+ return (ccs', rhs'))
+ ccs
pairs
bind = StgTopLifted $ StgRec (zip binders stg_rhss)
in
ASSERT2(consistentCafInfo (head binders) bind, ppr binders)
- (env', fvs' `unionFVInfo` body_fvs, ccs', bind)
+ (env', ccs', bind)
-- Assertion helper: this checks that the CafInfo on the Id matches
-- what CoreToStg has figured out about the binding's SRT. The
-- CafInfo will be exact in all cases except when CorePrep has
-- floated out a binding, in which case it will be approximate.
-consistentCafInfo :: Id -> GenStgTopBinding Var Id -> Bool
+consistentCafInfo :: Id -> StgTopBinding -> Bool
consistentCafInfo id bind
= WARN( not (exact || is_sat_thing) , ppr id <+> ppr id_marked_caffy <+> ppr binding_is_caffy )
safe
@@ -326,18 +320,17 @@ coreToTopStgRhs
-> CollectedCCs
-> Module
-> (Id,CoreExpr)
- -> CtsM (StgRhs, FreeVarsInfo, CollectedCCs)
+ -> CtsM (StgRhs, CollectedCCs)
coreToTopStgRhs dflags ccs this_mod (bndr, rhs)
- = do { (new_rhs, rhs_fvs) <- coreToStgExpr rhs
+ = do { new_rhs <- coreToStgExpr rhs
; let (stg_rhs, ccs') =
- mkTopStgRhs dflags this_mod ccs rhs_fvs bndr new_rhs
+ mkTopStgRhs dflags this_mod ccs bndr new_rhs
stg_arity =
stgRhsArity stg_rhs
; return (ASSERT2( arity_ok stg_arity, mk_arity_msg stg_arity) stg_rhs,
- rhs_fvs,
ccs') }
where
-- It's vital that the arity on a top-level Id matches
@@ -365,8 +358,7 @@ coreToTopStgRhs dflags ccs this_mod (bndr, rhs)
coreToStgExpr
:: CoreExpr
- -> CtsM (StgExpr, -- Decorated STG expr
- FreeVarsInfo) -- Its free vars (NB free, not live)
+ -> CtsM StgExpr
-- The second and third components can be derived in a simple bottom up pass, not
-- dependent on any decisions about which variables will be let-no-escaped or
@@ -378,7 +370,7 @@ coreToStgExpr
-- CorePrep should have converted them all to a real core representation.
coreToStgExpr (Lit (LitNumber LitNumInteger _ _)) = panic "coreToStgExpr: LitInteger"
coreToStgExpr (Lit (LitNumber LitNumNatural _ _)) = panic "coreToStgExpr: LitNatural"
-coreToStgExpr (Lit l) = return (StgLit l, emptyFVInfo)
+coreToStgExpr (Lit l) = return (StgLit l)
coreToStgExpr (App (Lit RubbishLit) _some_unlifted_type)
-- We lower 'RubbishLit' to @()@ here, which is much easier than doing it in
-- a STG to Cmm pass.
@@ -397,14 +389,13 @@ coreToStgExpr expr@(Lam _ _)
args' = filterStgBinders args
in
extendVarEnvCts [ (a, LambdaBound) | a <- args' ] $ do
- (body, body_fvs) <- coreToStgExpr body
+ body' <- coreToStgExpr body
let
- fvs = args' `minusFVBinders` body_fvs
result_expr = case nonEmpty args' of
- Nothing -> body
- Just args'' -> StgLam args'' body
+ Nothing -> body'
+ Just args'' -> StgLam args'' body'
- return (result_expr, fvs)
+ return result_expr
coreToStgExpr (Tick tick expr)
= do case tick of
@@ -412,8 +403,8 @@ coreToStgExpr (Tick tick expr)
ProfNote{} -> return ()
SourceNote{} -> return ()
Breakpoint{} -> panic "coreToStgExpr: breakpoint should not happen"
- (expr2, fvs) <- coreToStgExpr expr
- return (StgTick tick expr2, fvs)
+ expr2 <- coreToStgExpr expr
+ return (StgTick tick expr2)
coreToStgExpr (Cast expr _)
= coreToStgExpr expr
@@ -433,31 +424,9 @@ coreToStgExpr (Case scrut _ _ [])
coreToStgExpr (Case scrut bndr _ alts) = do
- (alts2, alts_fvs)
- <- extendVarEnvCts [(bndr, LambdaBound)] $ do
- (alts2, fvs_s) <- mapAndUnzipM vars_alt alts
- return ( alts2,
- unionFVInfos fvs_s )
- let
- -- Determine whether the default binder is dead or not
- -- This helps the code generator to avoid generating an assignment
- -- for the case binder (is extremely rare cases) ToDo: remove.
- bndr' | bndr `elementOfFVInfo` alts_fvs = bndr
- | otherwise = bndr `setIdOccInfo` IAmDead
-
- -- Don't consider the default binder as being 'live in alts',
- -- since this is from the point of view of the case expr, where
- -- the default binder is not free.
- alts_fvs_wo_bndr = bndr `minusFVBinder` alts_fvs
-
- -- We tell the scrutinee that everything
- -- live in the alts is live in it, too.
- (scrut2, scrut_fvs) <- coreToStgExpr scrut
-
- return (
- StgCase scrut2 bndr' (mkStgAltType bndr alts) alts2,
- scrut_fvs `unionFVInfo` alts_fvs_wo_bndr
- )
+ alts2 <- extendVarEnvCts [(bndr, LambdaBound)] (mapM vars_alt alts)
+ scrut2 <- coreToStgExpr scrut
+ return (StgCase scrut2 bndr (mkStgAltType bndr alts) alts2)
where
vars_alt (con, binders, rhs)
| DataAlt c <- con, c == unboxedUnitDataCon
@@ -465,16 +434,15 @@ coreToStgExpr (Case scrut bndr _ alts) = do
-- See Note [Nullary unboxed tuple] in Type.hs
-- where a nullary tuple is mapped to (State# World#)
ASSERT( null binders )
- do { (rhs2, rhs_fvs) <- coreToStgExpr rhs
- ; return ((DEFAULT, [], rhs2), rhs_fvs) }
+ do { rhs2 <- coreToStgExpr rhs
+ ; return (DEFAULT, [], rhs2) }
| otherwise
= let -- Remove type variables
binders' = filterStgBinders binders
in
extendVarEnvCts [(b, LambdaBound) | b <- binders'] $ do
- (rhs2, rhs_fvs) <- coreToStgExpr rhs
- return ( (con, binders', rhs2),
- binders' `minusFVBinders` rhs_fvs )
+ rhs2 <- coreToStgExpr rhs
+ return (con, binders', rhs2)
coreToStgExpr (Let bind body) = do
coreToStgLet bind body
@@ -533,19 +501,15 @@ coreToStgApp
-> Id -- Function
-> [CoreArg] -- Arguments
-> [Tickish Id] -- Debug ticks
- -> CtsM (StgExpr, FreeVarsInfo)
+ -> CtsM StgExpr
coreToStgApp _ f args ticks = do
- (args', args_fvs, ticks') <- coreToStgArgs args
+ (args', ticks') <- coreToStgArgs args
how_bound <- lookupVarCts f
let
n_val_args = valArgCount args
- fun_fvs = singletonFVInfo f how_bound
- -- e.g. (f :: a -> int) (x :: a)
- -- Here the free variables are "f", "x" AND the type variable "a"
- -- coreToStgArgs will deal with the arguments recursively
-- Mostly, the arity info of a function is in the fn's IdInfo
-- But new bindings introduced by CoreSat may not have no
@@ -579,45 +543,39 @@ coreToStgApp _ f args ticks = do
TickBoxOpId {} -> pprPanic "coreToStg TickBox" $ ppr (f,args')
_other -> StgApp f args'
- fvs = fun_fvs `unionFVInfo` args_fvs
tapp = foldr StgTick app (ticks ++ ticks')
-- Forcing these fixes a leak in the code generator, noticed while
-- profiling for trac #4367
- app `seq` fvs `seq` return (
- tapp,
- fvs
- )
+ app `seq` return tapp
-- ---------------------------------------------------------------------------
-- Argument lists
-- This is the guy that turns applications into A-normal form
-- ---------------------------------------------------------------------------
-coreToStgArgs :: [CoreArg] -> CtsM ([StgArg], FreeVarsInfo, [Tickish Id])
+coreToStgArgs :: [CoreArg] -> CtsM ([StgArg], [Tickish Id])
coreToStgArgs []
- = return ([], emptyFVInfo, [])
+ = return ([], [])
coreToStgArgs (Type _ : args) = do -- Type argument
- (args', fvs, ts) <- coreToStgArgs args
- return (args', fvs, ts)
+ (args', ts) <- coreToStgArgs args
+ return (args', ts)
coreToStgArgs (Coercion _ : args) -- Coercion argument; replace with place holder
- = do { (args', fvs, ts) <- coreToStgArgs args
- ; return (StgVarArg coercionTokenId : args', fvs, ts) }
+ = do { (args', ts) <- coreToStgArgs args
+ ; return (StgVarArg coercionTokenId : args', ts) }
coreToStgArgs (Tick t e : args)
= ASSERT( not (tickishIsCode t) )
- do { (args', fvs, ts) <- coreToStgArgs (e : args)
- ; return (args', fvs, t:ts) }
+ do { (args', ts) <- coreToStgArgs (e : args)
+ ; return (args', t:ts) }
coreToStgArgs (arg : args) = do -- Non-type argument
- (stg_args, args_fvs, ticks) <- coreToStgArgs args
- (arg', arg_fvs) <- coreToStgExpr arg
+ (stg_args, ticks) <- coreToStgArgs args
+ arg' <- coreToStgExpr arg
let
- fvs = args_fvs `unionFVInfo` arg_fvs
-
(aticks, arg'') = stripStgTicksTop tickishFloatable arg'
stg_arg = case arg'' of
StgApp v [] -> StgVarArg v
@@ -646,7 +604,7 @@ coreToStgArgs (arg : args) = do -- Non-type argument
-- We also want to check if a pointer is cast to a non-ptr etc
WARN( bad_args, text "Dangerous-looking argument. Probable cause: bad unsafeCoerce#" $$ ppr arg )
- return (stg_arg : stg_args, fvs, ticks ++ aticks)
+ return (stg_arg : stg_args, ticks ++ aticks)
-- ---------------------------------------------------------------------------
@@ -654,56 +612,43 @@ coreToStgArgs (arg : args) = do -- Non-type argument
-- ---------------------------------------------------------------------------
coreToStgLet
- :: CoreBind -- bindings
- -> CoreExpr -- body
- -> CtsM (StgExpr, -- new let
- FreeVarsInfo) -- variables free in the whole let
+ :: CoreBind -- bindings
+ -> CoreExpr -- body
+ -> CtsM StgExpr -- new let
coreToStgLet bind body = do
- (bind2, bind_fvs,
- body2, body_fvs)
+ (bind2, body2)
<- do
- ( bind2, bind_fvs, env_ext)
+ ( bind2, env_ext)
<- vars_bind bind
-- Do the body
extendVarEnvCts env_ext $ do
- (body2, body_fvs) <- coreToStgExpr body
+ body2 <- coreToStgExpr body
- return (bind2, bind_fvs,
- body2, body_fvs)
+ return (bind2, body2)
-- Compute the new let-expression
let
new_let | isJoinBind bind = StgLetNoEscape bind2 body2
| otherwise = StgLet bind2 body2
- free_in_whole_let
- = binders `minusFVBinders` (bind_fvs `unionFVInfo` body_fvs)
-
- return (
- new_let,
- free_in_whole_let
- )
+ return new_let
where
- binders = bindersOf bind
-
mk_binding binder rhs
= (binder, LetBound NestedLet (manifestArity rhs))
vars_bind :: CoreBind
-> CtsM (StgBinding,
- FreeVarsInfo,
[(Id, HowBound)]) -- extension to environment
vars_bind (NonRec binder rhs) = do
- (rhs2, bind_fvs) <- coreToStgRhs (binder,rhs)
+ rhs2 <- coreToStgRhs (binder,rhs)
let
env_ext_item = mk_binding binder rhs
- return (StgNonRec binder rhs2,
- bind_fvs, [env_ext_item])
+ return (StgNonRec binder rhs2, [env_ext_item])
vars_bind (Rec pairs)
= let
@@ -712,32 +657,26 @@ coreToStgLet bind body = do
| (b,rhs) <- pairs ]
in
extendVarEnvCts env_ext $ do
- (rhss2, fvss)
- <- mapAndUnzipM coreToStgRhs pairs
- let
- bind_fvs = unionFVInfos fvss
-
- return (StgRec (binders `zip` rhss2),
- bind_fvs, env_ext)
+ rhss2 <- mapM coreToStgRhs pairs
+ return (StgRec (binders `zip` rhss2), env_ext)
coreToStgRhs :: (Id,CoreExpr)
- -> CtsM (StgRhs, FreeVarsInfo)
+ -> CtsM StgRhs
coreToStgRhs (bndr, rhs) = do
- (new_rhs, rhs_fvs) <- coreToStgExpr rhs
- return (mkStgRhs rhs_fvs bndr new_rhs, rhs_fvs)
+ new_rhs <- coreToStgExpr rhs
+ return (mkStgRhs bndr new_rhs)
-- Generate a top-level RHS. Any new cost centres generated for CAFs will be
-- appended to `CollectedCCs` argument.
mkTopStgRhs :: DynFlags -> Module -> CollectedCCs
- -> FreeVarsInfo -> Id -> StgExpr
- -> (StgRhs, CollectedCCs)
+ -> Id -> StgExpr -> (StgRhs, CollectedCCs)
-mkTopStgRhs dflags this_mod ccs rhs_fvs bndr rhs
+mkTopStgRhs dflags this_mod ccs bndr rhs
| StgLam bndrs body <- rhs
= -- StgLam can't have empty arguments, so not CAF
- ( StgRhsClosure dontCareCCS
- (getFVs rhs_fvs)
+ ( StgRhsClosure noExtSilent
+ dontCareCCS
ReEntrant
(toList bndrs) body
, ccs )
@@ -752,14 +691,14 @@ mkTopStgRhs dflags this_mod ccs rhs_fvs bndr rhs
-- Otherwise it's a CAF, see Note [Cost-centre initialization plan].
| gopt Opt_AutoSccsOnIndividualCafs dflags
- = ( StgRhsClosure caf_ccs
- (getFVs rhs_fvs)
+ = ( StgRhsClosure noExtSilent
+ caf_ccs
upd_flag [] rhs
, collectCC caf_cc caf_ccs ccs )
| otherwise
- = ( StgRhsClosure all_cafs_ccs
- (getFVs rhs_fvs)
+ = ( StgRhsClosure noExtSilent
+ all_cafs_ccs
upd_flag [] rhs
, ccs )
@@ -783,18 +722,18 @@ mkTopStgRhs dflags this_mod ccs rhs_fvs bndr rhs
-- Generate a non-top-level RHS. Cost-centre is always currentCCS,
-- see Note [Cost-centre initialzation plan].
-mkStgRhs :: FreeVarsInfo -> Id -> StgExpr -> StgRhs
-mkStgRhs rhs_fvs bndr rhs
+mkStgRhs :: Id -> StgExpr -> StgRhs
+mkStgRhs bndr rhs
| StgLam bndrs body <- rhs
- = StgRhsClosure currentCCS
- (getFVs rhs_fvs)
+ = StgRhsClosure noExtSilent
+ currentCCS
ReEntrant
(toList bndrs) body
| isJoinId bndr -- must be a nullary join point
= ASSERT(idJoinArity bndr == 0)
- StgRhsClosure currentCCS
- (getFVs rhs_fvs)
+ StgRhsClosure noExtSilent
+ currentCCS
ReEntrant -- ignored for LNE
[] rhs
@@ -802,8 +741,8 @@ mkStgRhs rhs_fvs bndr rhs
= StgRhsCon currentCCS con args
| otherwise
- = StgRhsClosure currentCCS
- (getFVs rhs_fvs)
+ = StgRhsClosure noExtSilent
+ currentCCS
upd_flag [] rhs
where
(_, unticked_rhs) = stripStgTicksTop (not . tickishIsCode) rhs
@@ -891,11 +830,6 @@ data LetInfo
| NestedLet
deriving (Eq)
-topLevelBound :: HowBound -> Bool
-topLevelBound ImportBound = True
-topLevelBound (LetBound TopLet _) = True
-topLevelBound _ = False
-
-- For a let(rec)-bound variable, x, we record LiveInfo, the set of
-- variables that are live if x is live. This LiveInfo comprises
-- (a) dynamic live variables (ones with a non-top-level binding)
@@ -961,63 +895,6 @@ getAllCAFsCC this_mod =
in
(all_cafs_cc, all_cafs_ccs)
--- ---------------------------------------------------------------------------
--- Free variable information
--- ---------------------------------------------------------------------------
-
-type FreeVarsInfo = VarEnv (Var, HowBound)
- -- The Var is so we can gather up the free variables
- -- as a set.
- --
- -- The HowBound info just saves repeated lookups;
- -- we look up just once when we encounter the occurrence.
- -- INVARIANT: Any ImportBound Ids are HaveCafRef Ids
- -- Imported Ids without CAF refs are simply
- -- not put in the FreeVarsInfo for an expression.
- -- See singletonFVInfo and freeVarsToLiveVars
-
-emptyFVInfo :: FreeVarsInfo
-emptyFVInfo = emptyVarEnv
-
-singletonFVInfo :: Id -> HowBound -> FreeVarsInfo
--- Don't record non-CAF imports at all, to keep free-var sets small
-singletonFVInfo id ImportBound
- | mayHaveCafRefs (idCafInfo id) = unitVarEnv id (id, ImportBound)
- | otherwise = emptyVarEnv
-singletonFVInfo id how_bound = unitVarEnv id (id, how_bound)
-
-unionFVInfo :: FreeVarsInfo -> FreeVarsInfo -> FreeVarsInfo
-unionFVInfo fv1 fv2 = plusVarEnv_C plusFVInfo fv1 fv2
-
-unionFVInfos :: [FreeVarsInfo] -> FreeVarsInfo
-unionFVInfos fvs = foldr unionFVInfo emptyFVInfo fvs
-
-minusFVBinders :: [Id] -> FreeVarsInfo -> FreeVarsInfo
-minusFVBinders vs fv = foldr minusFVBinder fv vs
-
-minusFVBinder :: Id -> FreeVarsInfo -> FreeVarsInfo
-minusFVBinder v fv = fv `delVarEnv` v
- -- When removing a binder, remember to add its type variables
- -- c.f. CoreFVs.delBinderFV
-
-elementOfFVInfo :: Id -> FreeVarsInfo -> Bool
-elementOfFVInfo id fvs = isJust (lookupVarEnv fvs id)
-
--- Non-top-level things only, both type variables and ids
-getFVs :: FreeVarsInfo -> [Var]
-getFVs fvs = [id | (id, how_bound) <- nonDetEltsUFM fvs,
- -- It's OK to use nonDetEltsUFM here because we're not aiming for
- -- bit-for-bit determinism.
- -- See Note [Unique Determinism and code generation]
- not (topLevelBound how_bound) ]
-
-plusFVInfo :: (Var, HowBound)
- -> (Var, HowBound)
- -> (Var, HowBound)
-plusFVInfo (id1,hb1) (id2,hb2)
- = ASSERT(id1 == id2 && hb1 == hb2)
- (id1, hb1)
-
-- Misc.
filterStgBinders :: [Var] -> [Var]