[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / compiler / simplCore / FloatOut.lhs
index 654986c..659e7b2 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The GRASP/AQUA Project, Glasgow University, 1992-1996
+% (c) The GRASP/AQUA Project, Glasgow University, 1992-1998
 %
 \section[FloatOut]{Float bindings outwards (towards the top level)}
 
@@ -13,14 +13,18 @@ module FloatOut ( floatOutwards ) where
 import CoreSyn
 
 import CmdLineOpts     ( opt_D_verbose_core2core, opt_D_simplifier_stats )
+import ErrUtils                ( dumpIfSet )
 import CostCentre      ( dupifyCC, CostCentre )
-import Id              ( nullIdEnv, addOneToIdEnv, growIdEnvList, IdEnv,
-                         Id
-                       )
+import Id              ( Id )
+import Const           ( isWHNFCon )
+import VarEnv
+import CoreLint                ( beginPass, endPass )
 import PprCore
-import SetLevels       -- all of it
+import SetLevels       ( setLevels,
+                         Level(..), tOP_LEVEL, ltMajLvl, ltLvl, isTopLvl
+                       )
 import BasicTypes      ( Unused )
-import TyVar           ( TyVar )
+import Var             ( TyVar )
 import UniqSupply       ( UniqSupply )
 import List            ( partition )
 import Outputable
@@ -52,25 +56,17 @@ It turns out that this generates a subexpression of the form
 @
        \deq x ys -> let eq = eqFromEqDict deq in ...
 @
-which might usefully be separated to
+vwhich might usefully be separated to
 @
        \deq -> let eq = eqFromEqDict deq in \xy -> ...
 @
 Well, maybe.  We don't do this at the moment.
 
 \begin{code}
-type LevelledExpr  = GenCoreExpr    (Id, Level) Id Unused
-type LevelledBind  = GenCoreBinding (Id, Level) Id Unused
-type FloatingBind  = (Level, Floater)
-type FloatingBinds = [FloatingBind]
-
-data Floater
-  = LetFloater CoreBinding
-  | CaseFloater        (CoreExpr -> CoreExpr)
-               -- A CoreExpr with a hole in it:
-               -- "Give me a right-hand side of the
-               -- (usually single) alternative, and
-               -- I'll build the case..."
+type LevelledExpr  = TaggedExpr Level
+type LevelledBind  = TaggedBind Level
+type FloatBind     = (Level, CoreBind)
+type FloatBinds    = [FloatBind]
 \end{code}
 
 %************************************************************************
@@ -80,40 +76,38 @@ data Floater
 %************************************************************************
 
 \begin{code}
-floatOutwards :: UniqSupply -> [CoreBinding] -> [CoreBinding]
+floatOutwards :: UniqSupply -> [CoreBind] -> IO [CoreBind]
 
 floatOutwards us pgm
-  = case (setLevels pgm us) of { annotated_w_levels ->
-
-    case (unzip (map floatTopBind annotated_w_levels))
-               of { (fss, final_toplev_binds_s) ->
-
-    (if opt_D_verbose_core2core
-     then pprTrace "Levels added:\n"
-                  (vcat (map (ppr) annotated_w_levels))
-     else id
-    )
-    ( if not (opt_D_simplifier_stats) then
-        id
-      else
-        let
-           (tlets, ntlets, lams) = get_stats (sum_stats fss)
-        in
-        pprTrace "FloatOut stats: " (hcat [
-               int tlets,  ptext SLIT(" Lets floated to top level; "),
-               int ntlets, ptext SLIT(" Lets floated elsewhere; from "),
-               int lams,   ptext SLIT(" Lambda groups")])
-    )
-    concat final_toplev_binds_s
-    }}
+  = do {
+       beginPass "Float out";
+
+       let { annotated_w_levels = setLevels pgm us ;
+             (fss, binds_s')    = unzip (map floatTopBind annotated_w_levels)
+           } ;
+
+       dumpIfSet opt_D_verbose_core2core "Levels added:"
+                 (vcat (map ppr annotated_w_levels));
+
+       let { (tlets, ntlets, lams) = get_stats (sum_stats fss) };
+
+       dumpIfSet opt_D_simplifier_stats "FloatOut stats:"
+               (hcat [ int tlets,  ptext SLIT(" Lets floated to top level; "),
+                       int ntlets, ptext SLIT(" Lets floated elsewhere; from "),
+                       int lams,   ptext SLIT(" Lambda groups")]);
+
+       endPass "Float out" 
+               opt_D_verbose_core2core         {- no specific flag for dumping float-out -} 
+               (concat binds_s')
+    }
 
 floatTopBind bind@(NonRec _ _)
-  = case (floatBind nullIdEnv tOP_LEVEL bind) of { (fs, floats, bind', _) ->
+  = case (floatBind emptyVarEnv tOP_LEVEL bind) of { (fs, floats, bind', _) ->
     (fs, floatsToBinds floats ++ [bind'])
     }
 
 floatTopBind bind@(Rec _)
-  = case (floatBind nullIdEnv tOP_LEVEL bind) of { (fs, floats, Rec pairs', _) ->
+  = case (floatBind emptyVarEnv tOP_LEVEL bind) of { (fs, floats, Rec pairs', _) ->
        -- Actually floats will be empty
     --false:ASSERT(null floats)
     (fs, [Rec (floatsToBindPairs floats ++ pairs')])
@@ -131,7 +125,7 @@ floatTopBind bind@(Rec _)
 floatBind :: IdEnv Level
          -> Level
          -> LevelledBind
-         -> (FloatStats, FloatingBinds, CoreBinding, IdEnv Level)
+         -> (FloatStats, FloatBinds, CoreBind, IdEnv Level)
 
 floatBind env lvl (NonRec (name,level) rhs)
   = case (floatExpr env level rhs) of { (fs, rhs_floats, rhs') ->
@@ -141,7 +135,7 @@ floatBind env lvl (NonRec (name,level) rhs)
 
     (fs, rhs_floats',
      NonRec name (install heres rhs'),
-     addOneToIdEnv env name level)
+     extendVarEnv env name level)
     }}
 
 floatBind env lvl bind@(Rec pairs)
@@ -173,7 +167,7 @@ floatBind env lvl bind@(Rec pairs)
 
     }
   where
-    new_env = growIdEnvList env (map fst pairs)
+    new_env = extendVarEnvList env (map fst pairs)
 
     bind_level = getBindLevel bind
 
@@ -197,32 +191,33 @@ floatBind env lvl bind@(Rec pairs)
 floatExpr :: IdEnv Level
          -> Level
          -> LevelledExpr
-         -> (FloatStats, FloatingBinds, CoreExpr)
+         -> (FloatStats, FloatBinds, CoreExpr)
 
-floatExpr env _ (Var v)             = (zero_stats, [], Var v)
-floatExpr env _ (Lit l)      = (zero_stats, [], Lit l)
-floatExpr env _ (Prim op as) = (zero_stats, [], Prim op as)
-floatExpr env _ (Con con as) = (zero_stats, [], Con con as)
+floatExpr env _ (Var v)             = (zeroStats, [], Var v)
+floatExpr env _ (Type ty)    = (zeroStats, [], Type ty)
+floatExpr env lvl (Con con as) 
+  = case floatList (floatExpr env lvl) as of { (stats, floats, as') ->
+    (stats, floats, Con con as') }
          
 floatExpr env lvl (App e a)
-  = case (floatExpr env lvl e) of { (fs, floating_defns, e') ->
-    (fs, floating_defns, App e' a) }
+  = case (floatExpr env lvl e) of { (fse, floats_e, e') ->
+    case (floatExpr env lvl a) of { (fsa, floats_a, a') ->
+    (fse `add_stats` fsa, floats_e ++ floats_a, App e' a') }}
 
-floatExpr env lvl (Lam (TyBinder tv) e)
-  = let
-       incd_lvl = incMinorLvl lvl
-    in
-    case (floatExpr env incd_lvl e) of { (fs, floats, e') ->
+floatExpr env lvl (Lam (tv,incd_lvl) e)
+  | isTyVar tv
+  = case (floatExpr env incd_lvl e) of { (fs, floats, e') ->
 
        -- Dump any bindings which absolutely cannot go any further
     case (partitionByLevel incd_lvl floats)    of { (floats', heres) ->
 
-    (fs, floats', Lam (TyBinder tv) (install heres e'))
+    (fs, floats', Lam tv (install heres e'))
     }}
 
-floatExpr env lvl (Lam (ValBinder (arg,incd_lvl)) rhs)
-  = let
-       new_env  = addOneToIdEnv env arg incd_lvl
+floatExpr env lvl (Lam (arg,incd_lvl) rhs)
+  = ASSERT( isId arg )
+    let
+       new_env  = extendVarEnv env arg incd_lvl
     in
     case (floatExpr new_env incd_lvl rhs) of { (fs, floats, rhs') ->
 
@@ -231,35 +226,33 @@ floatExpr env lvl (Lam (ValBinder (arg,incd_lvl)) rhs)
 
     (add_to_stats fs floats',
      floats',
-     Lam (ValBinder arg) (install heres rhs'))
+     Lam arg (install heres rhs'))
     }}
 
 floatExpr env lvl (Note note@(SCC cc) expr)
   = case (floatExpr env lvl expr)    of { (fs, floating_defns, expr') ->
     let
-       -- annotate bindings floated outwards past an scc expression
+       -- Annotate bindings floated outwards past an scc expression
        -- with the cc.  We mark that cc as "duplicated", though.
 
        annotated_defns = annotate (dupifyCC cc) floating_defns
     in
     (fs, annotated_defns, Note note expr') }
   where
-    annotate :: CostCentre -> FloatingBinds -> FloatingBinds
+    annotate :: CostCentre -> FloatBinds -> FloatBinds
 
     annotate dupd_cc defn_groups
       = [ (level, ann_bind floater) | (level, floater) <- defn_groups ]
       where
-       ann_bind (LetFloater (NonRec binder rhs))
-         = LetFloater (NonRec binder (ann_rhs rhs))
+       ann_bind (NonRec binder rhs)
+         = NonRec binder (ann_rhs rhs)
 
-       ann_bind (LetFloater (Rec pairs))
-         = LetFloater (Rec [(binder, ann_rhs rhs) | (binder, rhs) <- pairs])
+       ann_bind (Rec pairs)
+         = Rec [(binder, ann_rhs rhs) | (binder, rhs) <- pairs]
 
-       ann_bind (CaseFloater fn) = CaseFloater ( \ rhs -> Note (SCC dupd_cc) (fn rhs) )
-
-       ann_rhs (Lam arg e)   = Lam arg (ann_rhs e)
-       ann_rhs rhs@(Con _ _) = rhs     -- no point in scc'ing WHNF data
-       ann_rhs rhs           = Note (SCC dupd_cc) rhs
+       ann_rhs (Lam arg e)     = Lam arg (ann_rhs e)
+       ann_rhs rhs@(Con con _) | isWHNFCon con = rhs   -- no point in scc'ing WHNF data
+       ann_rhs rhs             = Note (SCC dupd_cc) rhs
 
        -- Note: Nested SCC's are preserved for the benefit of
        --       cost centre stack profiling (Durham)
@@ -272,100 +265,37 @@ floatExpr env lvl (Let bind body)
   = case (floatBind env     lvl bind) of { (fsb, rhs_floats, bind', new_env) ->
     case (floatExpr new_env lvl body) of { (fse, body_floats, body') ->
     (add_stats fsb fse,
-     rhs_floats ++ [(bind_lvl, LetFloater bind')] ++ body_floats,
+     rhs_floats ++ [(bind_lvl, bind')] ++ body_floats,
      body')
     }}
   where
     bind_lvl = getBindLevel bind
 
-floatExpr env lvl (Case scrut alts)
-  = case (floatExpr env lvl scrut) of { (fse, fde, scrut') ->
-
-    case (scrut', float_alts alts) of
-       (_, (fsa, fda, alts')) ->
-               (add_stats fse fsa, fda ++ fde, Case scrut' alts')
-    }
-    {- OLD CASE-FLOATING CODE: DROPPED FOR NOW.  (SLPJ 7/2/94)
-
-       (Var scrut_var, (fda, AlgAlts [(con,bs,rhs')] NoDefault))
-               | scrut_var_lvl `ltMajLvl` lvl ->
-
-               -- Candidate for case floater; scrutinising a variable; it can
-               -- escape outside a lambda; there's only one alternative.
-               (fda ++ fde ++ [case_floater], rhs')
-
-               where
-               case_floater = (scrut_var_lvl, CaseFloater fn)
-               fn body = Case scrut' (AlgAlts [(con,bs,body)] NoDefault)
-               scrut_var_lvl = case lookupIdEnv env scrut_var of
-                                 Nothing  -> Level 0 0
-                                 Just lvl -> unTopify lvl
-
-    END OF CASE FLOATING DROPPED -}
+floatExpr env lvl (Case scrut (case_bndr, case_lvl) alts)
+  = case floatExpr env lvl scrut       of { (fse, fde, scrut') ->
+    case floatList float_alt alts      of { (fsa, fda, alts')  ->
+    (add_stats fse fsa, fda ++ fde, Case scrut' case_bndr alts')
+    }}
   where
-      incd_lvl = incMinorLvl lvl
+      alts_env = extendVarEnv env case_bndr case_lvl
 
       partition_fn = partitionByMajorLevel
 
-{-     OMITTED
-       We don't want to be too keen about floating lets out of case alternatives
-       because they may benefit from seeing the evaluation done by the case.
-
-       The main reason for doing this is to allocate in fewer larger blocks
-       but that's really an STG-level issue.
-
-                       case alts of
-                               -- Just one alternative, then dump only
-                               -- what *has* to be dumped
-                       AlgAlts  [_] NoDefault     -> partitionByLevel
-                       AlgAlts  []  (BindDefault _ _) -> partitionByLevel
-                       PrimAlts [_] NoDefault     -> partitionByLevel
-                       PrimAlts []  (BindDefault _ _) -> partitionByLevel
-
-                               -- If there's more than one alternative, then
-                               -- this is a dumping point
-                       other                              -> partitionByMajorLevel
--}
-
-      float_alts (AlgAlts alts deflt)
-       = case (float_deflt  deflt)              of { (fsd,  fdd,  deflt') ->
-         case (unzip3 (map float_alg_alt alts)) of { (fsas, fdas, alts') ->
-         (foldr add_stats fsd fsas,
-          concat fdas ++ fdd,
-          AlgAlts alts' deflt') }}
-
-      float_alts (PrimAlts alts deflt)
-       = case (float_deflt deflt)                of { (fsd,   fdd, deflt') ->
-         case (unzip3 (map float_prim_alt alts)) of { (fsas, fdas, alts') ->
-         (foldr add_stats fsd fsas,
-          concat fdas ++ fdd,
-          PrimAlts alts' deflt') }}
-
-      -------------
-      float_alg_alt (con, bs, rhs)
+      float_alt (con, bs, rhs)
        = let
              bs' = map fst bs
-             new_env = growIdEnvList env bs
+             new_env = extendVarEnvList alts_env bs
          in
-         case (floatExpr new_env incd_lvl rhs) of { (fs, rhs_floats, rhs') ->
-         case (partition_fn incd_lvl rhs_floats)       of { (rhs_floats', heres) ->
+         case (floatExpr new_env case_lvl rhs)         of { (fs, rhs_floats, rhs') ->
+         case (partition_fn case_lvl rhs_floats)       of { (rhs_floats', heres) ->
          (fs, rhs_floats', (con, bs', install heres rhs')) }}
 
-      --------------
-      float_prim_alt (lit, rhs)
-       = case (floatExpr env incd_lvl rhs)             of { (fs, rhs_floats, rhs') ->
-         case (partition_fn incd_lvl rhs_floats)       of { (rhs_floats', heres) ->
-         (fs, rhs_floats', (lit, install heres rhs')) }}
-
-      --------------
-      float_deflt NoDefault = (zero_stats, [], NoDefault)
-
-      float_deflt (BindDefault (b,lvl) rhs)
-       = case (floatExpr new_env lvl rhs)              of { (fs, rhs_floats, rhs') ->
-         case (partition_fn incd_lvl rhs_floats)       of { (rhs_floats', heres) ->
-         (fs, rhs_floats', BindDefault b (install heres rhs')) }}
-       where
-         new_env = addOneToIdEnv env b lvl
+
+floatList :: (a -> (FloatStats, FloatBinds, b)) -> [a] -> (FloatStats, FloatBinds, [b])
+floatList f [] = (zeroStats, [], [])
+floatList f (a:as) = case f a           of { (fs_a,  binds_a,  b)  ->
+                    case floatList f as of { (fs_as, binds_as, bs) ->
+                    (fs_a `add_stats` fs_as, binds_a ++ binds_as, b:bs) }}
 \end{code}
 
 %************************************************************************
@@ -385,9 +315,9 @@ data FloatStats
 
 get_stats (FlS a b c) = (a, b, c)
 
-zero_stats = FlS 0 0 0
+zeroStats = FlS 0 0 0
 
-sum_stats xs = foldr add_stats zero_stats xs
+sum_stats xs = foldr add_stats zeroStats xs
 
 add_stats (FlS a1 b1 c1) (FlS a2 b2 c2)
   = FlS (a1 + a2) (b1 + b2) (c1 + c2)
@@ -400,6 +330,7 @@ add_to_stats (FlS a b c) floats
     to_very_top (my_lvl, _) = isTopLvl my_lvl
 \end{code}
 
+
 %************************************************************************
 %*                                                                     *
 \subsection{Utility bits for floating}
@@ -415,10 +346,10 @@ getBindLevel (Rec (((_,lvl), _) : _)) = lvl
 partitionByMajorLevel, partitionByLevel
        :: Level                -- Partitioning level
 
-       -> FloatingBinds        -- Defns to be divided into 2 piles...
+       -> FloatBinds           -- Defns to be divided into 2 piles...
 
-       -> (FloatingBinds,      -- Defns  with level strictly < partition level,
-           FloatingBinds)      -- The rest
+       -> (FloatBinds, -- Defns  with level strictly < partition level,
+           FloatBinds) -- The rest
 
 
 partitionByMajorLevel ctxt_lvl defns
@@ -434,25 +365,20 @@ partitionByLevel ctxt_lvl defns
 \end{code}
 
 \begin{code}
-floatsToBinds :: FloatingBinds -> [CoreBinding]
-floatsToBinds floats = map get_bind floats
-                    where
-                      get_bind (_, LetFloater bind) = bind
-                      get_bind (_, CaseFloater _)   = panic "floatsToBinds"
+floatsToBinds :: FloatBinds -> [CoreBind]
+floatsToBinds floats = map snd floats
 
-floatsToBindPairs :: FloatingBinds -> [(Id,CoreExpr)]
+floatsToBindPairs :: FloatBinds -> [(Id,CoreExpr)]
 
 floatsToBindPairs floats = concat (map mk_pairs floats)
   where
-   mk_pairs (_, LetFloater (Rec pairs))         = pairs
-   mk_pairs (_, LetFloater (NonRec binder rhs)) = [(binder,rhs)]
-   mk_pairs (_, CaseFloater _)                           = panic "floatsToBindPairs"
+   mk_pairs (_, Rec pairs)         = pairs
+   mk_pairs (_, NonRec binder rhs) = [(binder,rhs)]
 
-install :: FloatingBinds -> CoreExpr -> CoreExpr
+install :: FloatBinds -> CoreExpr -> CoreExpr
 
 install defn_groups expr
   = foldr install_group expr defn_groups
   where
-    install_group (_, LetFloater defns) body = Let defns body
-    install_group (_, CaseFloater fn)   body = fn body
+    install_group (_, defns) body = Let defns body
 \end{code}