[project @ 2000-12-07 17:26:30 by simonmar]
authorsimonmar <unknown>
Thu, 7 Dec 2000 17:26:31 +0000 (17:26 +0000)
committersimonmar <unknown>
Thu, 7 Dec 2000 17:26:31 +0000 (17:26 +0000)
Figure out CafInfo during CoreTidy.  This is the final piece of the
puzzle in getting the final IdInfo from the Core2Core phases, rather
than waiting for the STG code.

This simplifies the SRT phase, in that it no longer has to have a
complicated circular algorithm to figure out the CafInfo at the same
time as the SRT layout.

ghc/compiler/coreSyn/CoreSat.lhs
ghc/compiler/coreSyn/CoreTidy.lhs
ghc/compiler/main/HscMain.lhs
ghc/compiler/nativeGen/MachRegs.lhs
ghc/compiler/nativeGen/RegAllocInfo.lhs
ghc/compiler/simplStg/SRT.lhs
ghc/compiler/stgSyn/StgSyn.lhs
ghc/compiler/utils/FastTypes.lhs

index acd0a4e..1b347d1 100644 (file)
@@ -161,8 +161,7 @@ coreSatExprFloat :: CoreExpr -> UniqSM ([FloatingBind], CoreExpr)
 --     f (g x)   ===>   ([v = g x], f v)
 
 coreSatExprFloat (Var v)
-  = fiddleCCall v  `thenUs` \ v ->
-    maybeSaturate v (Var v) 0 (idType v) `thenUs` \ app ->
+  = maybeSaturate v (Var v) 0 (idType v) `thenUs` \ app ->
     returnUs ([], app)
 
 coreSatExprFloat (Lit lit)
@@ -240,8 +239,7 @@ coreSatExprFloat expr@(App _ _)
          returnUs (App fun' arg', hd, res_ty, fs ++ floats, ss_rest)
 
     collect_args (Var v) depth
-       = fiddleCCall v   `thenUs` \ v ->
-         returnUs (Var v, (Var v, depth), idType v, [], stricts)
+       = returnUs (Var v, (Var v, depth), idType v, [], stricts)
        where
          stricts = case idStrictness v of
                        StrictnessInfo demands _ 
@@ -309,16 +307,6 @@ maybeSaturate fn expr n_args ty
     saturate_it  = getUs       `thenUs` \ us ->
                   returnUs (etaExpand excess_arity us expr ty)
 
-fiddleCCall id 
-  = case idFlavour id of
-         PrimOpId (CCallOp ccall) ->
-           -- Make a guaranteed unique name for a dynamic ccall.
-           getUniqueUs         `thenUs` \ uniq ->
-           returnUs (modifyIdInfo (`setFlavourInfo` 
-                           PrimOpId (CCallOp (setCCallUnique ccall uniq))) id)
-        other_flavour ->
-            returnUs id
-
 -- ---------------------------------------------------------------------------
 -- Eliminate Lam as a non-rhs (STG doesn't have such a thing)
 -- ---------------------------------------------------------------------------
index a9eeca5..18bba01 100644 (file)
@@ -14,34 +14,26 @@ module CoreTidy (
 import CmdLineOpts     ( DynFlags, DynFlag(..), opt_OmitInterfacePragmas )
 import CoreSyn
 import CoreUnfold      ( noUnfolding, mkTopUnfolding, okToUnfoldInHiFile )
-import CoreUtils       ( exprArity )
+import CoreUtils       ( exprArity, exprIsBottom )
 import CoreFVs         ( ruleSomeFreeVars, exprSomeFreeVars )
 import CoreLint                ( showPass, endPass )
 import VarEnv
 import VarSet
 import Var             ( Id, Var )
 import Id              ( idType, idInfo, idName, isExportedId,
-                         mkId, isLocalId, omitIfaceSigForId
+                         idCafInfo, mkId, isLocalId, omitIfaceSigForId,
+                         idFlavour, modifyIdInfo
                        ) 
-import IdInfo          ( IdInfo, mkIdInfo, vanillaIdInfo,
-                         IdFlavour(..), flavourInfo, ppFlavourInfo,
-                         specInfo, setSpecInfo, 
-                         cprInfo, setCprInfo, 
-                         inlinePragInfo, setInlinePragInfo, isNeverInlinePrag,
-                         strictnessInfo, setStrictnessInfo, 
-                         isBottomingStrictness,
-                         unfoldingInfo, setUnfoldingInfo, 
-                         occInfo, isLoopBreaker,
-                         workerInfo, setWorkerInfo, WorkerInfo(..),
-                         ArityInfo(..), setArityInfo
-                       )
+import IdInfo          {- loads of stuff -}
 import Name            ( getOccName, nameOccName, globaliseName, setNameOcc, 
                          localiseName, mkLocalName, isGlobalName
                        )
 import OccName         ( TidyOccEnv, initTidyOccEnv, tidyOccName )
 import Type            ( tidyTopType, tidyType, tidyTyVar )
 import Module          ( Module, moduleName )
-import HscTypes                ( PersistentCompilerState( pcs_PRS ), PersistentRenamerState( prsOrig ),
+import PrimOp          ( PrimOp(..), setCCallUnique )
+import HscTypes                ( PersistentCompilerState( pcs_PRS ), 
+                         PersistentRenamerState( prsOrig ),
                          OrigNameEnv( origNames ), OrigNameNameEnv
                        )
 import UniqSupply
@@ -51,6 +43,7 @@ import ErrUtils               ( showPass )
 import SrcLoc          ( noSrcLoc )
 import UniqFM          ( mapUFM )
 import Outputable
+import FastTypes
 import List            ( partition )
 import Util            ( mapAccumL )
 \end{code}
@@ -285,9 +278,11 @@ tidyTopBind :: Module
 tidyTopBind mod ext_ids env (NonRec bndr rhs)
   = ((us2,orig,occ,subst) , NonRec bndr' rhs')
   where
-    tidy_env                     = (occ,subst)
-    ((us1,orig,occ,subst), bndr') = tidyTopBinder mod ext_ids tidy_env rhs' env bndr
-    (rhs',us2)                   = initUs us1 (tidyExpr tidy_env rhs)
+    ((us1,orig,occ,subst), bndr')
+        = tidyTopBinder mod ext_ids tidy_env rhs' caf_info env bndr
+    tidy_env    = (occ,subst)
+    caf_info    = hasCafRefs (const True) rhs'
+    (rhs',us2)  = initUs us1 (tidyExpr tidy_env rhs)
 
 tidyTopBind mod ext_ids env (Rec prs)
   = (final_env, Rec prs')
@@ -298,15 +293,25 @@ tidyTopBind mod ext_ids env (Rec prs)
     do_one env (bndr,rhs) 
        = ((us',orig,occ,subst), (bndr',rhs'))
        where
-       ((us,orig,occ,subst), bndr') = tidyTopBinder mod ext_ids final_tidy_env rhs' env bndr
-        (rhs', us')                 = initUs us (tidyExpr final_tidy_env rhs)
+       ((us,orig,occ,subst), bndr')
+          = tidyTopBinder mod ext_ids final_tidy_env rhs' caf_info env bndr
+        (rhs', us')   = initUs us (tidyExpr final_tidy_env rhs)
+
+       -- the CafInfo for a recursive group says whether *any* rhs in
+       -- the group may refer indirectly to a CAF (because then, they all do).
+    (bndrs, rhss) = unzip prs'
+    caf_info = hasCafRefss pred rhss
+    pred v = v `notElem` bndrs
+
 
 tidyTopBinder :: Module -> IdEnv Bool
-             -> TidyEnv -> CoreExpr    -- The TidyEnv is used to tidy the IdInfo
-                                       -- The expr is the already-tided RHS
-                                       -- Both are knot-tied: don't look at them!
+             -> TidyEnv -> CoreExpr -> CafInfo
+                       -- The TidyEnv is used to tidy the IdInfo
+                       -- The expr is the already-tided RHS
+                       -- Both are knot-tied: don't look at them!
              -> TopTidyEnv -> Id -> (TopTidyEnv, Id)
-tidyTopBinder mod ext_ids tidy_env rhs 
+
+tidyTopBinder mod ext_ids tidy_env rhs caf_info
              env@(us, orig_env2, occ_env2, subst_env2) id
 
   | omitIfaceSigForId id       -- Don't mess with constructors, 
@@ -330,7 +335,7 @@ tidyTopBinder mod ext_ids tidy_env rhs
                                               (idName id)
     ty'                    = tidyTopType (idType id)
     idinfo'         = tidyIdInfo us_l tidy_env
-                        is_external unfold_info arity_info id
+                        is_external unfold_info arity_info caf_info id
 
     id'               = mkId name' ty' idinfo'
     subst_env' = extendVarEnv subst_env2 id id'
@@ -346,13 +351,14 @@ tidyTopBinder mod ext_ids tidy_env rhs
     arity_info = exprArity rhs
 
 
-tidyIdInfo us tidy_env is_external unfold_info arity_info id
+tidyIdInfo us tidy_env is_external unfold_info arity_info caf_info id
   | opt_OmitInterfacePragmas || not is_external
        -- No IdInfo if the Id isn't external, or if we don't have -O
   = mkIdInfo new_flavour 
        `setStrictnessInfo` strictnessInfo core_idinfo
        `setArityInfo`      ArityExactly arity_info
-       -- Keep strictness and arity info; it's used by the code generator
+       `setCafInfo`        caf_info
+       -- Keep strictness, arity and CAF info; it's used by the code generator
 
   | otherwise
   =  let (rules', _) = initUs us (tidyRules tidy_env (specInfo core_idinfo))
@@ -365,6 +371,7 @@ tidyIdInfo us tidy_env is_external unfold_info arity_info id
        `setWorkerInfo`     tidyWorker tidy_env (workerInfo core_idinfo)
        `setSpecInfo`       rules'
        `setArityInfo`      ArityExactly arity_info
+       `setCafInfo`        caf_info
                -- this is the final IdInfo, it must agree with the
                -- code finally generated (i.e. NO more transformations
                -- after this!).
@@ -459,7 +466,10 @@ tidyBind env (Rec prs)
     mapUs (tidyExpr env') (map snd prs)                `thenUs` \ rhss' ->
     returnUs (env', Rec (zip bndrs' rhss'))
 
-tidyExpr env (Var v)   = returnUs (Var (tidyVarOcc env v))
+tidyExpr env (Var v)   
+  = fiddleCCall v  `thenUs` \ v ->
+    returnUs (Var (tidyVarOcc env v))
+
 tidyExpr env (Type ty) = returnUs (Type (tidyType env ty))
 tidyExpr env (Lit lit) = returnUs (Lit lit)
 
@@ -514,7 +524,7 @@ tidyVarOcc (_, var_env) v = case lookupVarEnv var_env v of
 tidyBndr :: TidyEnv -> Var -> UniqSM (TidyEnv, Var)
 tidyBndr env var
   | isTyVar var = returnUs (tidyTyVar env var)
-  | otherwise   = tidyId env var vanillaIdInfo
+  | otherwise   = tidyId env var (vanillaIdInfo `setCafInfo` NoCafRefs)
 
 tidyBndrs :: TidyEnv -> [Var] -> UniqSM (TidyEnv, [Var])
 tidyBndrs env vars = mapAccumLUs tidyBndr env vars
@@ -525,6 +535,7 @@ tidyBndrWithRhs env (id,rhs)
    = tidyId env id idinfo
    where
        idinfo = vanillaIdInfo `setArityInfo` ArityExactly (exprArity rhs)
+                              `setCafInfo` NoCafRefs
                        -- NB: This throws away the IdInfo of the Id, which we
                        -- no longer need.  That means we don't need to
                        -- run over it with env, nor renumber it.
@@ -544,4 +555,80 @@ tidyId env@(tidy_env, var_env) id idinfo
        var_env'          = extendVarEnv var_env id id'
     in
     returnUs ((tidy_env', var_env'), id')
+
+
+fiddleCCall id 
+  = case idFlavour id of
+         PrimOpId (CCallOp ccall) ->
+           -- Make a guaranteed unique name for a dynamic ccall.
+           getUniqueUs         `thenUs` \ uniq ->
+           returnUs (modifyIdInfo (`setFlavourInfo` 
+                           PrimOpId (CCallOp (setCCallUnique ccall uniq))) id)
+        other_flavour ->
+            returnUs id
+\end{code}
+
+%************************************************************************
+%*                                                                     *
+\subsection{Figuring out CafInfo for an expression}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+hasCafRefs  :: (Id -> Bool) -> CoreExpr -> CafInfo
+hasCafRefss :: (Id -> Bool) -> [CoreExpr] -> CafInfo
+       -- predicate returns True for a given Id if we look at this Id when
+       -- calculating the result.  Used to *avoid* looking at the CafInfo
+       -- field for an Id that is part of the current recursive group.
+
+hasCafRefs p expr = if isCAF expr || isFastTrue (cafRefs p expr)
+                       then MayHaveCafRefs
+                       else NoCafRefs
+
+hasCafRefss p exprs = if any isCAF exprs || isFastTrue (cafRefss p exprs)
+                       then MayHaveCafRefs
+                       else NoCafRefs
+
+cafRefs p (Var id)
+ | p id
+ = case idCafInfo id of 
+       NoCafRefs      -> fastBool False
+       MayHaveCafRefs -> fastBool True
+ | otherwise
+ = fastBool False
+
+cafRefs p (Lit l)           = fastBool False
+cafRefs p (App f a)         = cafRefs p f `fastOr` cafRefs p a
+cafRefs p (Lam x e)         = cafRefs p e
+cafRefs p (Let b e)         = cafRefss p (rhssOfBind b) `fastOr` cafRefs p e
+cafRefs p (Case e bndr alts) = cafRefs p e `fastOr` cafRefss p (rhssOfAlts alts)
+cafRefs p (Note n e)        = cafRefs p e
+cafRefs p (Type t)          = fastBool False
+
+cafRefss p []    = fastBool False
+cafRefss p (e:es) = cafRefs p e `fastOr` cafRefss p es
+
+-- Decide whether a closure looks like a CAF or not.  In an effort to
+-- keep the number of CAFs (and hence the size of the SRTs) down, we
+-- would also like to look at the expression and decide whether it
+-- requires a small bounded amount of heap, so we can ignore it as a CAF.
+-- In these cases, we need to use an additional CAF list to keep track of
+-- non-collectable CAFs.
+-- 
+-- We mark real CAFs as `MayHaveCafRefs' because this information is used
+-- to decide whether a particular closure needs to be referenced in an
+-- SRT or not.
+
+isCAF :: CoreExpr -> Bool
+   -- special case for expressions which are always bottom,
+   -- such as 'error "..."'.  We don't need to record it as
+   -- a CAF, since it can only be entered once.
+isCAF e 
+  | not_function && is_bottom = False
+  | not_function && updatable = True
+  | otherwise                = False
+  where 
+    not_function = exprArity e == 0
+    is_bottom    = exprIsBottom e
+    updatable    = True {- ToDo: check type for onceness? -}
 \end{code}
index aa407b1..cf9bbe6 100644 (file)
@@ -38,11 +38,11 @@ import Type
 import InstEnv         ( emptyInstEnv )
 import Desugar
 import SimplCore
+import CoreSyn         ( bindersOfBinds )
 import CoreUtils       ( coreBindsSize )
 import CoreTidy                ( tidyCorePgm )
 import CoreSat
 import CoreToStg       ( coreToStg, coreExprToStg )
-import StgSyn          ( collectFinalStgBinders )
 import SimplStg                ( stg2stg )
 import CodeGen         ( codeGen )
 import CodeOutput      ( codeOutput )
@@ -218,26 +218,26 @@ hscRecomp ghci_mode dflags location maybe_checked_iface hst hit pcs_ch
            -- DESUGAR, SIMPLIFY, TIDY-CORE
            -------------------
          -- We grab the the unfoldings at this point.
-       ; simpl_result <- dsThenSimplThenTidy dflags pcs_tc hst this_mod 
-                                             print_unqualified is_exported tc_result
-       ; let (pcs_simpl, tidy_binds, orphan_rules, foreign_stuff) = simpl_result
+       ; (pcs_simpl, tidy_binds, orphan_rules, foreign_stuff)
+             <- dsThenSimplThenTidy dflags pcs_tc hst this_mod 
+                               print_unqualified is_exported tc_result
            
            -------------------
-           -- CONVERT TO STG
-           -------------------
-       ; (stg_binds, cost_centre_info, top_level_ids) 
-            <- myCoreToStg dflags this_mod tidy_binds
-
-
-           -------------------
            -- BUILD THE NEW ModDetails AND ModIface
            -------------------
        ; let new_details = mkModDetails env_tc tidy_binds 
-                                        top_level_ids orphan_rules
+                               (bindersOfBinds tidy_binds) orphan_rules
        ; final_iface <- mkFinalIface ghci_mode dflags location 
                                       maybe_checked_iface new_iface new_details
 
            -------------------
+           -- CONVERT TO STG
+           -------------------
+       ; (stg_binds, cost_centre_info) 
+               <- myCoreToStg dflags this_mod tidy_binds
+
+
+           -------------------
            -- COMPLETE CODE GENERATION
            -------------------
        ; (maybe_stub_h_filename, maybe_stub_c_filename, maybe_ibinds)
@@ -381,9 +381,8 @@ myCoreToStg dflags this_mod tidy_binds
 
       -- _scc_     "Stg2Stg"
       (stg_binds2, cost_centre_info) <- stg2stg dflags this_mod stg_binds
-      let final_ids = collectFinalStgBinders (map fst stg_binds2)
 
-      return (stg_binds2, cost_centre_info, final_ids)
+      return (stg_binds2, cost_centre_info)
 \end{code}
 
 
index 6ef3594..2417cb9 100644 (file)
@@ -812,7 +812,7 @@ allMachRegNos
 -- register allocator to attempt to map VRegs to.
 allocatableRegs :: [Reg]
 allocatableRegs
-   = let isFree i = _IS_TRUE_(freeReg i)
+   = let isFree i = isFastTrue (freeReg i)
      in  map RealReg (filter isFree allMachRegNos)
 
 -------------------------------
index 4cc220b..6461871 100644 (file)
@@ -148,7 +148,7 @@ regUsage :: Instr -> RegUsage
 interesting (VirtualRegI _)  = True
 interesting (VirtualRegF _)  = True
 interesting (VirtualRegD _)  = True
-interesting (RealReg i)      = _IS_TRUE_(freeReg i)
+interesting (RealReg i)      = isFastTrue (freeReg i)
 
 #if alpha_TARGET_ARCH
 
index 4989c3f..c597baa 100644 (file)
@@ -9,8 +9,9 @@ bindings have no CAF references, and record the fact in their IdInfo.
 \begin{code}
 module SRT where
 
-import Id        ( Id, setIdCafInfo, idCafInfo, externallyVisibleId )
-import CoreUtils ( idAppIsBottom )
+#include "HsVersions.h"
+
+import Id        ( Id, idCafInfo )
 import IdInfo   ( CafInfo(..) )
 import StgSyn
 
@@ -25,48 +26,31 @@ import Outputable
 
 \begin{code}
 computeSRTs :: [StgBinding] -> [(StgBinding,[Id])]
-computeSRTs binds = srtBinds emptyUFM binds
-\end{code}
-
-\begin{code}
-srtBinds :: UniqFM CafInfo -> [StgBinding] -> [(StgBinding,[Id])] 
-srtBinds rho [] = []
-srtBinds rho (b:bs) = 
-       srtTopBind rho b   =: \(b, srt, rho) ->
-       (b,srt) : srtBinds rho bs
+computeSRTs binds = map srtTopBind binds
 \end{code}
 
 -----------------------------------------------------------------------------
-Circular algorithm for simultaneously figuring out CafInfo and SRT
-layout.
+Algorithm for figuring out SRT layout.
 
 Our functions have type
 
-       :: UniqFM CafInfo       -- which top-level ids don't refer to any CAfs
-       -> SrtOffset            -- next free offset within the SRT
+       :: SrtOffset            -- next free offset within the SRT
        -> (UniqSet Id,         -- global refs in the continuation
            UniqFM (UniqSet Id))-- global refs in let-no-escaped variables
 {- * -}        -> StgExpr              -- expression to analyse
 
        -> (StgExpr,            -- (e) newly annotated expression
-           UniqSet Id,         -- (g) set of *all* global references
+           UniqSet Id,         -- (g) global refs from this expression
            [Id],               -- (s) SRT required for this expression
            SrtOffset)          -- (o) new offset
 
 (g) is a set containing all local top-level and imported ids referred
-to by the expression (e).
-
-The set of all global references is used to build the environment,
-which is passed in again.  The environment is used to build the final
-SRT.
+to by the expression (e), which have MayHaveCafRefs in their CafInfo.
 
 We build a single SRT for a recursive binding group, which is why the
 SRT building is done at the binding level rather than the
 StgRhsClosure level.
 
-Hence, the only argument which we can look at before returning is the
-expression (marked with {- * -} above).
-
 The SRT is built up in reverse order, to avoid too many expensive
 appends.  We therefore reverse the SRT before returning it, so that
 the offsets will be from the beginning of the SRT.
@@ -74,14 +58,6 @@ the offsets will be from the beginning of the SRT.
 -----------------------------------------------------------------------------
 Top-level Bindings
 
-The environment contains a mapping from local top-level bindings to
-CafInfo.  The CafInfo is either
-
-       NoCafRefs      - indicating that the id is not a CAF and furthermore
-                        that it doesn't refer, even indirectly, to any CAFs.
-       
-       MayHaveCafRefs - everything else.
-
 A function whose CafInfo is NoCafRefs will have an empty SRT, and its
 closure will not appear in the SRT of any other function (unless we're
 compiling without optimisation and the CafInfos haven't been emitted
@@ -94,9 +70,8 @@ single SRT for the whole group, and we'd rather not have recursive
 references in it if at all possible.
 
 We collect all the global references for the group, and filter out
-those that are binders in the group and not CAFs themselves.  This set
-of references is then used to infer the CafInfo for each of the
-binders in the group.  Why is it done this way?
+those that are binders in the group and not CAFs themselves.  Why is
+it done this way?
 
        - if all the bindings in the group just refer to each other,
          and none of them are CAFs, we'd like to get an empty SRT.
@@ -108,62 +83,51 @@ Hmm, that probably makes no sense.
 
 \begin{code}
 srtTopBind 
-       :: UniqFM CafInfo
-       -> StgBinding
+       :: StgBinding
        -> (StgBinding,                 -- the new binding
-           [Id],                       -- the SRT for this binding
-           UniqFM CafInfo)             -- the new environment
+           [Id])                       -- the SRT for this binding
 
-srtTopBind rho (StgNonRec binder rhs) =
+srtTopBind (StgNonRec binder rhs) =
 
    -- no need to use circularity for non-recursive bindings
-   srtRhs rho (emptyUniqSet,emptyUFM) 0{-initial offset-} rhs
+   srtRhs (emptyUniqSet,emptyUFM) 0{-initial offset-} rhs
                                        =: \(rhs, g, srt, off) ->
    let
-       filtered_g = filter (mayHaveCafRefs rho) (uniqSetToList g)
-        caf_info   = mk_caf_info rhs filtered_g
-       binder'    = setIdCafInfo binder caf_info
-        rho'       = addToUFM rho binder' caf_info
+       filtered_g = uniqSetToList g
         extra_refs = filter (`notElem` srt) filtered_g
        bind_srt   = reverse (extra_refs ++ srt)
    in
+   ASSERT2(null bind_srt || mayHaveCafRefs binder, ppr binder)
+
    case rhs of
         StgRhsClosure _ _ _ _ _ _ _ ->
-           (StgNonRec binder' (attach_srt_rhs rhs 0 (length bind_srt)), 
-            bind_srt, rho')
+           (StgNonRec binder (attach_srt_rhs rhs 0 (length bind_srt)), 
+            bind_srt)
 
-       -- don't output an SRT for the constructor, but just remember
-       -- whether it had any caf references or not.
-       StgRhsCon _ _ _    -> (StgNonRec binder' rhs, [], rho')
+       -- don't output an SRT for the constructor
+       StgRhsCon _ _ _    -> (StgNonRec binder rhs, [])
 
 
-srtTopBind rho (StgRec bs) =
-    (attach_srt_bind (StgRec (reverse new_bs')) 0 (length bind_srt), 
-       bind_srt, rho')
+srtTopBind (StgRec bs) =
+    ASSERT(null bind_srt || all mayHaveCafRefs binders)
+    (attach_srt_bind (StgRec new_bs) 0 (length bind_srt), bind_srt)
   where
     (binders,rhss) = unzip bs
     
     non_caf_binders = [ b | (b, rhs) <- bs, not (caf_rhs rhs) ]
 
-    -- circular: rho' is calculated from g below
     (new_bs, g, srt, _) = doBinds bs [] emptyUniqSet [] 0
 
     -- filter out ourselves from the global references: it makes no
     -- sense to refer recursively to our SRT unless the recursive
     -- reference is required by a nested SRT.
-    filtered_g = filter (\id -> id `notElem` non_caf_binders && 
-                               mayHaveCafRefs rho id) (uniqSetToList g)
+    filtered_g = filter (\id -> id `notElem` non_caf_binders) (uniqSetToList g)
     extra_refs = filter (`notElem` srt) filtered_g
     bind_srt = reverse (extra_refs ++ srt)
-    caf_infos = map (\rhs -> mk_caf_info rhs filtered_g) rhss
-    rho' = addListToUFM rho (zip binders caf_infos)
-    binders' = zipWith setIdCafInfo binders caf_infos
-
-    new_bs' = zip binders' (map snd new_bs)
 
     doBinds [] new_binds g srt off = (reverse new_binds, g, srt, off)
     doBinds ((binder,rhs):binds) new_binds g srt off =
-       srtRhs rho' (emptyUniqSet,emptyUFM) off rhs 
+       srtRhs (emptyUniqSet,emptyUFM) off rhs 
                                =: \(rhs, rhs_g, rhs_srt, off) ->
        let 
            g'   = unionUniqSets rhs_g g
@@ -179,22 +143,22 @@ caf_rhs _ = False
 Non-top-level bindings
 
 \begin{code}
-srtBind :: UniqFM CafInfo -> (UniqSet Id, UniqFM (UniqSet Id))
+srtBind :: (UniqSet Id, UniqFM (UniqSet Id))
        -> Int -> StgBinding -> (StgBinding, UniqSet Id, [Id], Int)
 
-srtBind rho cont_refs off (StgNonRec binder rhs) =
-  srtRhs rho cont_refs off rhs   =: \(rhs, g, srt, off) ->
+srtBind cont_refs off (StgNonRec binder rhs) =
+  srtRhs cont_refs off rhs   =: \(rhs, g, srt, off) ->
   (StgNonRec binder rhs, g, srt, off)
 
-srtBind rho cont_refs off (StgRec binds) =
-    (StgRec new_binds, g, srt, new_off)
+srtBind cont_refs off (StgRec binds) =
+  (StgRec new_binds, g, srt, new_off)
   where
     -- process each binding
     (new_binds, g, srt, new_off) = doBinds binds emptyUniqSet [] off []
 
     doBinds [] g srt off new_binds = (reverse new_binds, g, srt, off)
     doBinds ((binder,rhs):binds) g srt off new_binds =
-        srtRhs rho cont_refs off rhs   =: \(rhs, g', srt', off) ->
+        srtRhs cont_refs off rhs   =: \(rhs, g', srt', off) ->
        doBinds binds (unionUniqSets g g') (srt'++srt) off
                ((binder,rhs):new_binds)
 \end{code}
@@ -203,46 +167,46 @@ srtBind rho cont_refs off (StgRec binds) =
 Right Hand Sides
 
 \begin{code}
-srtRhs         :: UniqFM CafInfo -> (UniqSet Id, UniqFM (UniqSet Id))
+srtRhs         :: (UniqSet Id, UniqFM (UniqSet Id))
        -> Int -> StgRhs -> (StgRhs, UniqSet Id, [Id], Int)
 
-srtRhs rho cont off (StgRhsClosure cc bi old_srt free_vars u args body) =
-    srtExpr rho cont off body  =: \(body, g, srt, off) ->
+srtRhs cont off (StgRhsClosure cc bi old_srt free_vars u args body) =
+    srtExpr cont off body      =: \(body, g, srt, off) ->
     (StgRhsClosure cc bi old_srt free_vars u args body, g, srt, off)
 
-srtRhs rho cont off e@(StgRhsCon cc con args) =
-    (e, getGlobalRefs rho args, [], off)
+srtRhs cont off e@(StgRhsCon cc con args) =
+    (e, getGlobalRefs args, [], off)
 \end{code}
 
 -----------------------------------------------------------------------------
 Expressions
 
 \begin{code}
-srtExpr :: UniqFM CafInfo -> (UniqSet Id, UniqFM (UniqSet Id))
+srtExpr :: (UniqSet Id, UniqFM (UniqSet Id))
        -> Int -> StgExpr -> (StgExpr, UniqSet Id, [Id], Int)
 
-srtExpr rho (cont,lne) off e@(StgApp f args) = (e, global_refs, [], off)
+srtExpr (cont,lne) off e@(StgApp f args) = (e, global_refs, [], off)
   where global_refs = 
                cont `unionUniqSets`
-               getGlobalRefs rho (StgVarArg f:args) `unionUniqSets`
+               getGlobalRefs (StgVarArg f:args) `unionUniqSets`
                lookupPossibleLNE lne f
 
-srtExpr rho (cont,lne) off e@(StgLit l) = (e, cont, [], off)
+srtExpr (cont,lne) off e@(StgLit l) = (e, cont, [], off)
 
-srtExpr rho (cont,lne) off e@(StgConApp con args) =
-   (e, cont `unionUniqSets` getGlobalRefs rho args, [], off)
+srtExpr (cont,lne) off e@(StgConApp con args) =
+   (e, cont `unionUniqSets` getGlobalRefs args, [], off)
 
-srtExpr rho (cont,lne) off e@(StgPrimApp op args ty) =
-   (e, cont `unionUniqSets` getGlobalRefs rho args, [], off)
+srtExpr (cont,lne) off e@(StgPrimApp op args ty) =
+   (e, cont `unionUniqSets` getGlobalRefs args, [], off)
 
-srtExpr rho c@(cont,lne) off (StgCase scrut live1 live2 uniq _{-srt-} alts) =
-   srtCaseAlts rho c off alts =: \(alts, alts_g, alts_srt, alts_off) ->
+srtExpr c@(cont,lne) off (StgCase scrut live1 live2 uniq _{-srt-} alts) =
+   srtCaseAlts c off alts =: \(alts, alts_g, alts_srt, alts_off) ->
 
        -- construct the SRT for this case
-   let (this_srt, scrut_off) = construct_srt rho alts_g alts_srt alts_off in
+   let (this_srt, scrut_off) = construct_srt alts_g alts_srt alts_off in
 
        -- global refs in the continuation is alts_g.
-   srtExpr rho (alts_g,lne) scrut_off scrut
+   srtExpr (alts_g,lne) scrut_off scrut
                                =: \(scrut, scrut_g, scrut_srt, case_off) ->
    let
        g = unionUniqSets alts_g scrut_g
@@ -253,35 +217,35 @@ srtExpr rho c@(cont,lne) off (StgCase scrut live1 live2 uniq _{-srt-} alts) =
    in
    (StgCase scrut live1 live2 uniq srt_info alts, g, srt, case_off)
 
-srtExpr rho cont off (StgLet bind body) =
-   srtLet rho cont off bind body StgLet (\_ cont -> cont)
+srtExpr cont off (StgLet bind body) =
+   srtLet cont off bind body StgLet (\_ cont -> cont)
 
-srtExpr rho cont off (StgLetNoEscape live1 live2 b@(StgNonRec bndr rhs) body)
-  = srtLet rho cont off b body (StgLetNoEscape live1 live2) calc_cont
+srtExpr cont off (StgLetNoEscape live1 live2 b@(StgNonRec bndr rhs) body)
+  = srtLet cont off b body (StgLetNoEscape live1 live2) calc_cont
   where calc_cont g (cont,lne) = (cont,addToUFM lne bndr g)
 
 -- for recursive let-no-escapes, we do *two* passes, the first time
 -- just to extract the list of global refs, and the second time we actually
 -- construct the SRT now that we know what global refs should be in
 -- the various let-no-escape continuations.
-srtExpr rho conts@(cont,lne) off 
+srtExpr conts@(cont,lne) off 
        (StgLetNoEscape live1 live2 bind@(StgRec pairs) body)
-  = srtBind rho conts off bind =: \(_, g, _, _) ->
+  = srtBind conts off bind =: \(_, g, _, _) ->
     let 
        lne' = addListToUFM lne [ (bndr,g) | (bndr,_) <- pairs ]
        calc_cont _ conts = conts
     in
-    srtLet rho (cont,lne') off bind body (StgLetNoEscape live1 live2) calc_cont
+    srtLet (cont,lne') off bind body (StgLetNoEscape live1 live2) calc_cont
 
 
-srtExpr rho cont off (StgSCC cc expr) =
-   srtExpr rho cont off expr   =: \(expr, g, srt, off) ->
+srtExpr cont off (StgSCC cc expr) =
+   srtExpr cont off expr       =: \(expr, g, srt, off) ->
    (StgSCC cc expr, g, srt, off)
 
 #ifdef DEBUG
-srtExpr rho cont off expr = pprPanic "srtExpr" (ppr expr)
+srtExpr cont off expr = pprPanic "srtExpr" (ppr expr)
 #else
-srtExpr rho cont off expr = panic "srtExpr"
+srtExpr cont off expr = panic "srtExpr"
 #endif
 \end{code}
 
@@ -291,13 +255,13 @@ Let-expressions
 This is quite complicated stuff...
 
 \begin{code}
-srtLet rho cont off bind body let_constr calc_cont
+srtLet cont off bind body let_constr calc_cont
 
  -- If the bindings are all constructors, then we don't need to
  -- buid an SRT at all...
  | all_con_binds bind =
-   srtBind rho cont off bind   =: \(bind, bind_g, bind_srt, off) ->
-   srtExpr rho cont off body   =: \(body, body_g, body_srt, off) ->
+   srtBind cont off bind       =: \(bind, bind_g, bind_srt, off) ->
+   srtExpr cont off body       =: \(body, body_g, body_srt, off) ->
    let
        g   = unionUniqSets bind_g body_g
        srt = body_srt ++ bind_srt
@@ -308,16 +272,16 @@ srtLet rho cont off bind body let_constr calc_cont
  | otherwise =
 
     -- first, find the sub-SRTs in the binding
-   srtBind rho cont off bind   =: \(bind, bind_g, bind_srt, bind_off) ->
+   srtBind cont off bind       =: \(bind, bind_g, bind_srt, bind_off) ->
 
     -- construct the SRT for this binding
-   let (this_srt, body_off) = construct_srt rho bind_g bind_srt bind_off in
+   let (this_srt, body_off) = construct_srt bind_g bind_srt bind_off in
 
     -- get the new continuation information (if a let-no-escape)
    let new_cont = calc_cont bind_g cont in
 
     -- now find the SRTs in the body
-   srtExpr rho new_cont body_off body  =: \(body, body_g, body_srt, let_off) ->
+   srtExpr new_cont body_off body  =: \(body, body_g, body_srt, let_off) ->
 
    let
        -- union all the global references together
@@ -340,10 +304,9 @@ references which aren't already contained in one of the sub-SRTs (and
 which are "live").
 
 \begin{code}
-construct_srt rho global_refs sub_srt current_offset
+construct_srt global_refs sub_srt current_offset
    = let
-       extra_refs = filter (`notElem` sub_srt) 
-                     (filter (mayHaveCafRefs rho) (uniqSetToList global_refs))
+       extra_refs = filter (`notElem` sub_srt) (uniqSetToList global_refs)
        this_srt = extra_refs ++ sub_srt
 
        -- Add the length of the new entries to the     
@@ -356,130 +319,74 @@ construct_srt rho global_refs sub_srt current_offset
 Case Alternatives
 
 \begin{code}
-srtCaseAlts :: UniqFM CafInfo -> (UniqSet Id, UniqFM (UniqSet Id))
+srtCaseAlts :: (UniqSet Id, UniqFM (UniqSet Id))
        -> Int -> StgCaseAlts -> (StgCaseAlts, UniqSet Id, [Id], Int)
 
-srtCaseAlts rho cont off (StgAlgAlts t alts dflt) =
-   srtAlgAlts rho cont off alts [] emptyUniqSet []  
+srtCaseAlts cont off (StgAlgAlts t alts dflt) =
+   srtAlgAlts cont off alts [] emptyUniqSet []  
                                  =: \(alts, alts_g, alts_srt, off) ->
-   srtDefault rho cont off dflt          =: \(dflt, dflt_g, dflt_srt, off) ->
+   srtDefault cont off dflt      =: \(dflt, dflt_g, dflt_srt, off) ->
    let
        g   = unionUniqSets alts_g dflt_g
        srt = dflt_srt ++ alts_srt
    in
    (StgAlgAlts t alts dflt, g, srt, off)
 
-srtCaseAlts rho cont off (StgPrimAlts t alts dflt) =
-   srtPrimAlts rho cont off alts [] emptyUniqSet []  
+srtCaseAlts cont off (StgPrimAlts t alts dflt) =
+   srtPrimAlts cont off alts [] emptyUniqSet []  
                                   =: \(alts, alts_g, alts_srt, off) ->
-   srtDefault rho cont off dflt           =: \(dflt, dflt_g, dflt_srt, off) ->
+   srtDefault cont off dflt       =: \(dflt, dflt_g, dflt_srt, off) ->
    let
        g   = unionUniqSets alts_g dflt_g
        srt = dflt_srt ++ alts_srt
    in
    (StgPrimAlts t alts dflt, g, srt, off)
 
-srtAlgAlts rho cont off [] new_alts g srt = (reverse new_alts, g, srt, off)
-srtAlgAlts rho cont off ((con,args,used,rhs):alts) new_alts g srt =
-   srtExpr rho cont off rhs    =: \(rhs, rhs_g, rhs_srt, off) ->
+srtAlgAlts cont off [] new_alts g srt = (reverse new_alts, g, srt, off)
+srtAlgAlts cont off ((con,args,used,rhs):alts) new_alts g srt =
+   srtExpr cont off rhs        =: \(rhs, rhs_g, rhs_srt, off) ->
    let
        g'   = unionUniqSets rhs_g g
        srt' = rhs_srt ++ srt
    in
-   srtAlgAlts rho cont off alts ((con,args,used,rhs) : new_alts) g' srt'
+   srtAlgAlts cont off alts ((con,args,used,rhs) : new_alts) g' srt'
 
-srtPrimAlts rho cont off [] new_alts g srt = (reverse new_alts, g, srt, off)
-srtPrimAlts rho cont off ((lit,rhs):alts) new_alts g srt =
-   srtExpr rho cont off rhs    =: \(rhs, rhs_g, rhs_srt, off) ->
+srtPrimAlts cont off [] new_alts g srt = (reverse new_alts, g, srt, off)
+srtPrimAlts cont off ((lit,rhs):alts) new_alts g srt =
+   srtExpr cont off rhs        =: \(rhs, rhs_g, rhs_srt, off) ->
    let
        g'   = unionUniqSets rhs_g g
        srt' = rhs_srt ++ srt
    in
-   srtPrimAlts rho cont off alts ((lit,rhs) : new_alts) g' srt'
+   srtPrimAlts cont off alts ((lit,rhs) : new_alts) g' srt'
 
-srtDefault rho cont off StgNoDefault = (StgNoDefault,emptyUniqSet,[],off)
-srtDefault rho cont off (StgBindDefault rhs) =
-   srtExpr rho cont off rhs    =: \(rhs, g, srt, off) ->
+srtDefault cont off StgNoDefault = (StgNoDefault,emptyUniqSet,[],off)
+srtDefault cont off (StgBindDefault rhs) =
+   srtExpr cont off rhs        =: \(rhs, g, srt, off) ->
    (StgBindDefault rhs, g, srt, off)
 \end{code}
 
 -----------------------------------------------------------------------------
 
-Decide whether a closure looks like a CAF or not.  In an effort to
-keep the number of CAFs (and hence the size of the SRTs) down, we
-would also like to look at the expression and decide whether it
-requires a small bounded amount of heap, so we can ignore it as a CAF.
-In these cases, we need to use an additional CAF list to keep track of
-non-collectable CAFs.
-
-We mark real CAFs as `MayHaveCafRefs' because this information is used
-to decide whether a particular closure needs to be referenced in an
-SRT or not.
-
-\begin{code}
-mk_caf_info 
-       :: StgRhs                       -- right-hand-side of the definition
-       -> [Id]                         -- static references
-       -> CafInfo
-
--- special case for expressions which are always bottom,
--- such as 'error "..."'.  We don't need to record it as
--- a CAF, since it can only be entered once.
-mk_caf_info (StgRhsClosure _ _ _ free_vars _ [] e) srt
-        | isBottomingExpr e && null srt = NoCafRefs
-
-mk_caf_info (StgRhsClosure _ _ _ free_vars upd args body) srt 
-       | isUpdatable upd = MayHaveCafRefs -- a real live CAF
-       | null srt  = NoCafRefs          -- function w/ no static references
-       | otherwise = MayHaveCafRefs     -- function w/ some static references
-
-mk_caf_info rcon@(StgRhsCon cc con args) srt 
-       | null srt   = NoCafRefs         -- constructor w/ no static references
-       | otherwise  = MayHaveCafRefs    -- otherwise, treat as a CAF
-
-
-isBottomingExpr (StgLet bind expr) = isBottomingExpr expr
-isBottomingExpr (StgApp f args)    = idAppIsBottom f (length args)
-isBottomingExpr _                 = False
-\end{code}
-
------------------------------------------------------------------------------
-
 Here we decide which Id's to place in the static reference table.  An
 internal top-level id will be in the environment with the appropriate
 CafInfo, so we use that if available.  An imported top-level Id will
 have the CafInfo attached.  Otherwise, we just ignore the Id.
 
 \begin{code}
-getGlobalRefs :: UniqFM CafInfo -> [StgArg] -> UniqSet Id
-getGlobalRefs rho args = mkUniqSet (concat (map (globalRefArg rho) args))
-
-globalRefArg :: UniqFM CafInfo -> StgArg -> [Id]
-
-globalRefArg rho (StgVarArg id)
-
-  | otherwise =
-    case lookupUFM rho id of {
-       Just _ -> [id];                 -- Can't look at the caf_info yet...
-        Nothing ->                     -- but we will look it up and filter later
-                                       -- in maybeHaveCafRefs
-
-    if externallyVisibleId id 
-       then case idCafInfo id of
-               MayHaveCafRefs -> [id]
-               NoCafRefs      -> []
-       else []
-   }
-
-globalRefArg rho _ = []
-\end{code}
-
-\begin{code}
-mayHaveCafRefs rho id =
-  case lookupUFM rho id of
-       Just MayHaveCafRefs -> True
-       Just NoCafRefs      -> False
-       Nothing             -> True
+getGlobalRefs :: [StgArg] -> UniqSet Id
+getGlobalRefs args = mkUniqSet (concat (map globalRefArg args))
+
+globalRefArg :: StgArg -> [Id]
+globalRefArg (StgVarArg id)
+  | mayHaveCafRefs id = [id]
+  | otherwise         = []
+globalRefArg _ = []
+
+mayHaveCafRefs id
+ = case idCafInfo id of
+       MayHaveCafRefs -> True
+       NoCafRefs      -> False
 \end{code}
 
 -----------------------------------------------------------------------------
@@ -550,17 +457,9 @@ calling z recursively.
 
 FIX:
 
-The following code fixes up a let-no-escape expression after we've run
-the SRT algorithm.  It needs to know the SRT for the *whole*
-expression (this is plugged in instead of the SRT for case exprsesions
-in the body).  The good news is that we only need to traverse nested
-case expressions, since the let-no-escape bound variable can't occur
-in the rhs of a let or in a case scrutinee.
-
-For recursive let-no-escapes, the body is processed as for
-non-recursive let-no-escapes, but case expressions in the rhs of each
-binding have their SRTs replaced with the SRT for the binding group
-(*not* the SRT of the whole let-no-escape expression).
+We keep track of the global references made by each let-no-escape in
+scope, so we can expand them every time the let-no-escape is
+referenced.
 
 \begin{code}
 lookupPossibleLNE lne_env f = 
index c0d94bc..82477d5 100644 (file)
@@ -34,8 +34,7 @@ module StgSyn (
        pprStgBinding, pprStgBindings, pprStgBindingsWithSRTs,
        getArgPrimRep, pprStgAlts,
        isLitLitArg, isDllConApp, isStgTypeArg,
-       stgArity, stgArgType,
-       collectFinalStgBinders
+       stgArity, stgArgType
 
 #ifdef DEBUG
        , pprStgLVs
@@ -547,27 +546,6 @@ pprSRT (SRT off len) = parens (ppr off <> comma <> ppr len)
 
 %************************************************************************
 %*                                                                     *
-\subsection[Stg-utility-functions]{Utility functions}
-%*                                                                     *
-%************************************************************************
-
-
-For doing interfaces, we want the exported top-level Ids from the
-final pre-codegen STG code, so as to be sure we have the
-latest/greatest pragma info.
-
-\begin{code}
-collectFinalStgBinders
-       :: [StgBinding] -- input program
-       -> [Id]
-
-collectFinalStgBinders [] = []
-collectFinalStgBinders (StgNonRec b _ : binds) = b : collectFinalStgBinders binds
-collectFinalStgBinders (StgRec bs     : binds) = map fst bs ++ collectFinalStgBinders binds
-\end{code}
-
-%************************************************************************
-%*                                                                     *
 \subsection[Stg-pretty-printing]{Pretty-printing}
 %*                                                                     *
 %************************************************************************
index 07df3c3..e335848 100644 (file)
@@ -9,7 +9,7 @@ module FastTypes (
     (+#), (-#), (*#), quotFastInt, negateFastInt,
     (==#), (<#), (<=#), (>=#), (>#),
 
-    FastBool, fastBool, _IS_TRUE_
+    FastBool, fastBool, isFastTrue, fastOr
   ) where
 
 #if defined(__GLASGOW_HASKELL__)
@@ -30,7 +30,13 @@ negateFastInt = negateInt#
 type FastBool = Int#
 fastBool True  = 1#
 fastBool False = 0#
-_IS_TRUE_ x = x ==# 1#
+isFastTrue x = x ==# 1#
+
+fastOr 1# _ = 1#
+fastOr 0# x = x
+
+fastAnd 0# x = 0#
+fastAnd 1# x = x
 
 #else {- ! __GLASGOW_HASKELL__ -}