[project @ 2003-08-15 11:31:02 by simonmar]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CorePrep.lhs
index 61f7d0a..18444b6 100644 (file)
@@ -10,29 +10,32 @@ module CorePrep (
 
 #include "HsVersions.h"
 
-import CoreUtils( exprIsAtom, exprType, exprIsValue, etaExpand, exprArity, exprOkForSpeculation )
+import CoreUtils( exprType, exprIsValue, etaExpand, exprArity, exprOkForSpeculation )
 import CoreFVs ( exprFreeVars )
 import CoreLint        ( endPass )
 import CoreSyn
-import Type    ( Type, applyTy, splitFunTy_maybe, isTyVarTy,
-                 isUnLiftedType, isUnboxedTupleType, repType,  
-                 uaUTy, usOnce, usMany, eqUsage, seqType )
+import Type    ( Type, applyTy, splitFunTy_maybe, 
+                 isUnLiftedType, isUnboxedTupleType, seqType )
+import TcType  ( TyThing( AnId ) )
 import NewDemand  ( Demand, isStrictDmd, lazyDmd, StrictSig(..), DmdType(..) )
-import PrimOp  ( PrimOp(..) )
 import Var     ( Var, Id, setVarUnique )
 import VarSet
 import VarEnv
 import Id      ( mkSysLocal, idType, idNewDemandInfo, idArity,
-                 setIdType, isPrimOpId_maybe, isFCallId, isGlobalId, 
-                 hasNoBinding, idNewStrictness, setIdArity
+                 isFCallId, isGlobalId, isImplicitId,
+                 isLocalId, hasNoBinding, idNewStrictness, 
+                 idUnfolding, isDataConWorkId_maybe
                )
-import HscTypes ( ModDetails(..) )
-import BasicTypes ( Arity, TopLevelFlag(..), isTopLevel )
+import HscTypes   ( TypeEnv, typeEnvElts )
+import BasicTypes ( TopLevelFlag(..), isTopLevel, isNotTopLevel,
+                   RecFlag(..), isNonRec
+                 )
 import UniqSupply
 import Maybes
 import OrdList
 import ErrUtils
 import CmdLineOpts
+import Util       ( listLengthCmp )
 import Outputable
 \end{code}
 
@@ -61,39 +64,56 @@ The goal of this pass is to prepare for code generation.
 4.  Ensure that lambdas only occur as the RHS of a binding
     (The code generator can't deal with anything else.)
 
-5.  Do the seq/par munging.  See notes with mkCase below.
+5.  [Not any more; nuked Jun 2002] Do the seq/par munging.
+
+6.  Clone all local Ids.
+    This means that all such Ids are unique, rather than the 
+    weaker guarantee of no clashes which the simplifier provides.
+    And that is what the code generator needs.
+
+    We don't clone TyVars. The code gen doesn't need that, 
+    and doing so would be tiresome because then we'd need
+    to substitute in types.
 
-6.  Clone all local Ids.  This means that Tidy Core has the property
-    that all Ids are unique, rather than the weaker guarantee of
-    no clashes which the simplifier provides.
 
 7.  Give each dynamic CCall occurrence a fresh unique; this is
     rather like the cloning step above.
 
+8.  Inject bindings for the "implicit" Ids:
+       * Constructor wrappers
+       * Constructor workers
+       * Record selectors
+    We want curried definitions for all of these in case they
+    aren't inlined by some caller.
+       
 This is all done modulo type applications and abstractions, so that
 when type erasure is done for conversion to STG, we don't end up with
 any trivial or useless bindings.
 
   
 
-
 -- -----------------------------------------------------------------------------
 -- Top level stuff
 -- -----------------------------------------------------------------------------
 
 \begin{code}
-corePrepPgm :: DynFlags -> ModDetails -> IO ModDetails
-corePrepPgm dflags mod_details
+corePrepPgm :: DynFlags -> [CoreBind] -> TypeEnv -> IO [CoreBind]
+corePrepPgm dflags binds types
   = do showPass dflags "CorePrep"
        us <- mkSplitUniqSupply 's'
 
-       let floats    = initUs_ us (corePrepTopBinds emptyVarEnv (md_binds mod_details))
-           new_binds = foldrOL get [] floats
-           get (FloatLet b) bs = b:bs
-           get b            bs = pprPanic "corePrepPgm" (ppr b)
+       let implicit_binds = mkImplicitBinds types
+               -- NB: we must feed mkImplicitBinds through corePrep too
+               -- so that they are suitably cloned and eta-expanded
 
-        endPass dflags "CorePrep" Opt_D_dump_prep new_binds
-       return (mod_details { md_binds = new_binds })
+           binds_out = initUs_ us (
+                         corePrepTopBinds binds        `thenUs` \ floats1 ->
+                         corePrepTopBinds implicit_binds       `thenUs` \ floats2 ->
+                         returnUs (deFloatTop (floats1 `appendFloats` floats2))
+                       )
+           
+        endPass dflags "CorePrep" Opt_D_dump_prep binds_out
+       return binds_out
 
 corePrepExpr :: DynFlags -> CoreExpr -> IO CoreExpr
 corePrepExpr dflags expr
@@ -103,7 +123,54 @@ corePrepExpr dflags expr
        dumpIfSet_dyn dflags Opt_D_dump_prep "CorePrep" 
                     (ppr new_expr)
        return new_expr
+\end{code}
+
+-- -----------------------------------------------------------------------------
+-- Implicit bindings
+-- -----------------------------------------------------------------------------
+
+Create any necessary "implicit" bindings (data constructors etc).
+Namely:
+       * Constructor workers
+       * Constructor wrappers
+       * Data type record selectors
+       * Class op selectors
+
+In the latter three cases, the Id contains the unfolding to use for
+the binding.  In the case of data con workers we create the rather 
+strange (non-recursive!) binding
+
+       $wC = \x y -> $wC x y
 
+i.e. a curried constructor that allocates.  This means that we can
+treat the worker for a constructor like any other function in the rest
+of the compiler.  The point here is that CoreToStg will generate a
+StgConApp for the RHS, rather than a call to the worker (which would
+give a loop).  As Lennart says: the ice is thin here, but it works.
+
+Hmm.  Should we create bindings for dictionary constructors?  They are
+always fully applied, and the bindings are just there to support
+partial applications. But it's easier to let them through.
+
+\begin{code}
+mkImplicitBinds type_env
+  = [ NonRec id (get_unfolding id)
+    | AnId id <- typeEnvElts type_env, isImplicitId id ]
+       -- The type environment already contains all the implicit Ids, 
+       -- so we just filter them out
+       --
+       -- The etaExpand is so that the manifest arity of the
+       -- binding matches its claimed arity, which is an 
+       -- invariant of top level bindings going into the code gen
+
+get_unfolding id       -- See notes above
+  | Just data_con <- isDataConWorkId_maybe id = Var id -- The ice is thin here, but it works
+                                                       -- CorePrep will eta-expand it
+  | otherwise                                = unfoldingTemplate (idUnfolding id)
+\end{code}
+       
+
+\begin{code}
 -- ---------------------------------------------------------------------------
 -- Dealing with bindings
 -- ---------------------------------------------------------------------------
@@ -112,34 +179,81 @@ data FloatingBind = FloatLet CoreBind
                  | FloatCase Id CoreExpr Bool
                        -- The bool indicates "ok-for-speculation"
 
-instance Outputable FloatingBind where
-  ppr (FloatLet bind)        = text "FloatLet" <+> ppr bind
-  ppr (FloatCase b rhs spec) = text "FloatCase" <+> ppr b <+> ppr spec <+> equals <+> ppr rhs
+data Floats = Floats OkToSpec (OrdList FloatingBind)
 
-type CloneEnv = IdEnv Id       -- Clone local Ids
+-- Can we float these binds out of the rhs of a let?  We cache this decision
+-- to avoid having to recompute it in a non-linear way when there are
+-- deeply nested lets.
+data OkToSpec
+   = NotOkToSpec       -- definitely not
+   | OkToSpec          -- yes
+   | IfUnboxedOk       -- only if floating an unboxed binding is ok
+
+emptyFloats :: Floats
+emptyFloats = Floats OkToSpec nilOL
 
-allLazy :: OrdList FloatingBind -> Bool
-allLazy floats 
-  = foldrOL check True floats
+addFloat :: Floats -> FloatingBind -> Floats
+addFloat (Floats ok_to_spec floats) new_float
+  = Floats (combine ok_to_spec (check new_float)) (floats `snocOL` new_float)
   where
-    check (FloatLet _)               y = y
-    check (FloatCase _ _ ok_for_spec) y = ok_for_spec && y
+    check (FloatLet _)               = OkToSpec
+    check (FloatCase _ _ ok_for_spec) 
+       | ok_for_spec  =  IfUnboxedOk
+       | otherwise    =  NotOkToSpec
        -- The ok-for-speculation flag says that it's safe to
        -- float this Case out of a let, and thereby do it more eagerly
        -- We need the top-level flag because it's never ok to float
        -- an unboxed binding to the top level
 
+unitFloat :: FloatingBind -> Floats
+unitFloat = addFloat emptyFloats
+
+appendFloats :: Floats -> Floats -> Floats
+appendFloats (Floats spec1 floats1) (Floats spec2 floats2)
+  = Floats (combine spec1 spec2) (floats1 `appOL` floats2)
+
+concatFloats :: [Floats] -> Floats
+concatFloats = foldr appendFloats emptyFloats
+
+combine NotOkToSpec _ = NotOkToSpec
+combine _ NotOkToSpec = NotOkToSpec
+combine IfUnboxedOk _ = IfUnboxedOk
+combine _ IfUnboxedOk = IfUnboxedOk
+combine _ _           = OkToSpec
+    
+instance Outputable FloatingBind where
+  ppr (FloatLet bind)        = text "FloatLet" <+> ppr bind
+  ppr (FloatCase b rhs spec) = text "FloatCase" <+> ppr b <+> ppr spec <+> equals <+> ppr rhs
+
+type CloneEnv = IdEnv Id       -- Clone local Ids
+
+deFloatTop :: Floats -> [CoreBind]
+-- For top level only; we don't expect any FloatCases
+deFloatTop (Floats _ floats)
+  = foldrOL get [] floats
+  where
+    get (FloatLet b) bs = b:bs
+    get b           bs = pprPanic "corePrepPgm" (ppr b)
+
+allLazy :: TopLevelFlag -> RecFlag -> Floats -> Bool
+allLazy top_lvl is_rec (Floats ok_to_spec _)
+  = case ok_to_spec of
+       OkToSpec -> True
+       NotOkToSpec -> False
+       IfUnboxedOk -> isNotTopLevel top_lvl && isNonRec is_rec
+
 -- ---------------------------------------------------------------------------
 --                     Bindings
 -- ---------------------------------------------------------------------------
 
-corePrepTopBinds :: CloneEnv -> [CoreBind] -> UniqSM (OrdList FloatingBind)
-corePrepTopBinds env [] = returnUs nilOL
-
-corePrepTopBinds env (bind : binds)
-  = corePrepTopBind env bind           `thenUs` \ (env', bind') ->
-    corePrepTopBinds env' binds                `thenUs` \ binds' ->
-    returnUs (bind' `appOL` binds')
+corePrepTopBinds :: [CoreBind] -> UniqSM Floats
+corePrepTopBinds binds 
+  = go emptyVarEnv binds
+  where
+    go env []            = returnUs emptyFloats
+    go env (bind : binds) = corePrepTopBind env bind   `thenUs` \ (env', bind') ->
+                           go env' binds               `thenUs` \ binds' ->
+                           returnUs (bind' `appendFloats` binds')
 
 -- NB: we do need to float out of top-level bindings
 -- Consider    x = length [True,False]
@@ -154,21 +268,37 @@ corePrepTopBinds env (bind : binds)
 --     a = g y
 --     x* = f a
 -- And then x will actually end up case-bound
+--
+-- What happens to the CafInfo on the floated bindings?  By
+-- default, all the CafInfos will be set to MayHaveCafRefs,
+-- which is safe.
+--
+-- This might be pessimistic, because eg. s1 & s2
+-- might not refer to any CAFs and the GC will end up doing
+-- more traversal than is necessary, but it's still better
+-- than not floating the bindings at all, because then
+-- the GC would have to traverse the structure in the heap
+-- instead.  Given this, we decided not to try to get
+-- the CafInfo on the floated bindings correct, because
+-- it looks difficult.
 
-corePrepTopBind :: CloneEnv -> CoreBind -> UniqSM (CloneEnv, OrdList FloatingBind)
+--------------------------------
+corePrepTopBind :: CloneEnv -> CoreBind -> UniqSM (CloneEnv, Floats)
 corePrepTopBind env (NonRec bndr rhs) 
-  = cloneBndr env bndr                         `thenUs` \ (env', bndr') ->
-    corePrepRhs TopLevel env (bndr, rhs)       `thenUs` \ (floats, rhs') -> 
-    returnUs (env', floats `snocOL` FloatLet (NonRec bndr' rhs'))
+  = cloneBndr env bndr                                 `thenUs` \ (env', bndr') ->
+    corePrepRhs TopLevel NonRecursive env (bndr, rhs)  `thenUs` \ (floats, rhs') -> 
+    returnUs (env', addFloat floats (FloatLet (NonRec bndr' rhs')))
 
 corePrepTopBind env (Rec pairs) = corePrepRecPairs TopLevel env pairs
 
-corePrepBind ::  CloneEnv -> CoreBind -> UniqSM (CloneEnv, OrdList FloatingBind)
+--------------------------------
+corePrepBind ::  CloneEnv -> CoreBind -> UniqSM (CloneEnv, Floats)
        -- This one is used for *local* bindings
 corePrepBind env (NonRec bndr rhs)
-  = corePrepExprFloat env rhs                          `thenUs` \ (floats, rhs') ->
+  = etaExpandRhs bndr rhs                              `thenUs` \ rhs1 ->
+    corePrepExprFloat env rhs1                         `thenUs` \ (floats, rhs2) ->
     cloneBndr env bndr                                 `thenUs` \ (env', bndr') ->
-    mkLocalNonRec bndr' (bdrDem bndr') floats rhs'     `thenUs` \ floats' ->
+    mkLocalNonRec bndr' (bdrDem bndr') floats rhs2     `thenUs` \ floats' ->
     returnUs (env', floats')
 
 corePrepBind env (Rec pairs) = corePrepRecPairs NotTopLevel env pairs
@@ -176,20 +306,29 @@ corePrepBind env (Rec pairs) = corePrepRecPairs NotTopLevel env pairs
 --------------------------------
 corePrepRecPairs :: TopLevelFlag -> CloneEnv
                 -> [(Id,CoreExpr)]     -- Recursive bindings
-                -> UniqSM (CloneEnv, OrdList FloatingBind)
+                -> UniqSM (CloneEnv, Floats)
 -- Used for all recursive bindings, top level and otherwise
 corePrepRecPairs lvl env pairs
-  = cloneBndrs env (map fst pairs)             `thenUs` \ (env', bndrs') ->
-    mapAndUnzipUs (corePrepRhs lvl env') pairs `thenUs` \ (floats_s, rhss') ->
-    returnUs (env', concatOL floats_s `snocOL` FloatLet (Rec (bndrs' `zip` rhss')))
+  = cloneBndrs env (map fst pairs)                             `thenUs` \ (env', bndrs') ->
+    mapAndUnzipUs (corePrepRhs lvl Recursive env') pairs       `thenUs` \ (floats_s, rhss') ->
+    returnUs (env', unitFloat (FloatLet (Rec (flatten (concatFloats floats_s) bndrs' rhss'))))
+  where
+       -- Flatten all the floats, and the currrent
+       -- group into a single giant Rec
+    flatten (Floats _ floats) bndrs rhss = foldrOL get (bndrs `zip` rhss) floats
+
+    get (FloatLet (NonRec b r)) prs2 = (b,r) : prs2
+    get (FloatLet (Rec prs1))   prs2 = prs1 ++ prs2
 
 --------------------------------
-corePrepRhs :: TopLevelFlag -> CloneEnv -> (Id, CoreExpr)
-           -> UniqSM (OrdList FloatingBind, CoreExpr)
+corePrepRhs :: TopLevelFlag -> RecFlag
+           -> CloneEnv -> (Id, CoreExpr)
+           -> UniqSM (Floats, CoreExpr)
 -- Used for top-level bindings, and local recursive bindings
-corePrepRhs top_lvl env (bndr, rhs)
-  = corePrepExprFloat env rhs          `thenUs` \ floats_w_rhs ->
-    floatRhs top_lvl bndr floats_w_rhs
+corePrepRhs top_lvl is_rec env (bndr, rhs)
+  = etaExpandRhs bndr rhs      `thenUs` \ rhs' ->
+    corePrepExprFloat env rhs' `thenUs` \ floats_w_rhs ->
+    floatRhs top_lvl is_rec bndr floats_w_rhs
 
 
 -- ---------------------------------------------------------------------------
@@ -198,22 +337,17 @@ corePrepRhs top_lvl env (bndr, rhs)
 
 -- This is where we arrange that a non-trivial argument is let-bound
 corePrepArg :: CloneEnv -> CoreArg -> RhsDemand
-          -> UniqSM (OrdList FloatingBind, CoreArg)
+          -> UniqSM (Floats, CoreArg)
 corePrepArg env arg dem
   = corePrepExprFloat env arg          `thenUs` \ (floats, arg') ->
-    if no_binding_needed arg'
+    if exprIsTrivial arg'
     then returnUs (floats, arg')
-    else newVar (exprType arg') (exprArity arg')       `thenUs` \ v ->
-        mkLocalNonRec v dem floats arg'                `thenUs` \ floats' -> 
+    else newVar (exprType arg')                        `thenUs` \ v ->
+        mkLocalNonRec v dem floats arg'        `thenUs` \ floats' -> 
         returnUs (floats', Var v)
 
-no_binding_needed | opt_RuntimeTypes = exprIsAtom
-                 | otherwise        = exprIsTrivial
-
 -- version that doesn't consider an scc annotation to be trivial.
-exprIsTrivial (Var v)
-  | hasNoBinding v                    = idArity v == 0
-  | otherwise                          = True
+exprIsTrivial (Var v)                 = True
 exprIsTrivial (Type _)                = True
 exprIsTrivial (Lit lit)               = True
 exprIsTrivial (App e arg)             = isTypeArg arg && exprIsTrivial e
@@ -232,7 +366,7 @@ corePrepAnExpr env expr
     mkBinds floats expr
 
 
-corePrepExprFloat :: CloneEnv -> CoreExpr -> UniqSM (OrdList FloatingBind, CoreExpr)
+corePrepExprFloat :: CloneEnv -> CoreExpr -> UniqSM (Floats, CoreExpr)
 -- If
 --     e  ===>  (bs, e')
 -- then        
@@ -245,39 +379,41 @@ corePrepExprFloat env (Var v)
   = fiddleCCall v                              `thenUs` \ v1 ->
     let v2 = lookupVarEnv env v1 `orElse` v1 in
     maybeSaturate v2 (Var v2) 0 (idType v2)    `thenUs` \ app ->
-    returnUs (nilOL, app)
+    returnUs (emptyFloats, app)
 
 corePrepExprFloat env expr@(Type _)
-  = returnUs (nilOL, expr)
+  = returnUs (emptyFloats, expr)
 
 corePrepExprFloat env expr@(Lit lit)
-  = returnUs (nilOL, expr)
+  = returnUs (emptyFloats, expr)
 
 corePrepExprFloat env (Let bind body)
   = corePrepBind env bind              `thenUs` \ (env', new_binds) ->
     corePrepExprFloat env' body                `thenUs` \ (floats, new_body) ->
-    returnUs (new_binds `appOL` floats, new_body)
+    returnUs (new_binds `appendFloats` floats, new_body)
 
 corePrepExprFloat env (Note n@(SCC _) expr)
   = corePrepAnExpr env expr            `thenUs` \ expr1 ->
-    deLam expr1                                `thenUs` \ expr2 ->
-    returnUs (nilOL, Note n expr2)
+    deLamFloat expr1                   `thenUs` \ (floats, expr2) ->
+    returnUs (floats, Note n expr2)
 
 corePrepExprFloat env (Note other_note expr)
   = corePrepExprFloat env expr         `thenUs` \ (floats, expr') ->
     returnUs (floats, Note other_note expr')
 
 corePrepExprFloat env expr@(Lam _ _)
-  = corePrepAnExpr env body            `thenUs` \ body' ->
-    returnUs (nilOL, mkLams bndrs body')
+  = cloneBndrs env bndrs               `thenUs` \ (env', bndrs') ->
+    corePrepAnExpr env' body           `thenUs` \ body' ->
+    returnUs (emptyFloats, mkLams bndrs' body')
   where
     (bndrs,body) = collectBinders expr
 
 corePrepExprFloat env (Case scrut bndr alts)
-  = corePrepExprFloat env scrut                `thenUs` \ (floats, scrut') ->
+  = corePrepExprFloat env scrut                `thenUs` \ (floats1, scrut1) ->
+    deLamFloat scrut1                  `thenUs` \ (floats2, scrut2) ->
     cloneBndr env bndr                 `thenUs` \ (env', bndr') ->
     mapUs (sat_alt env') alts          `thenUs` \ alts' ->
-    returnUs (floats, mkCase scrut' bndr' alts')
+    returnUs (floats1 `appendFloats` floats2 , Case scrut2 bndr' alts')
   where
     sat_alt env (con, bs, rhs)
          = cloneBndrs env bs           `thenUs` \ (env', bs') ->
@@ -311,7 +447,7 @@ corePrepExprFloat env expr@(App _ _)
                   (CoreExpr,Int),        -- the head of the application,
                                          -- and no. of args it was applied to
                   Type,                  -- type of the whole expr
-                  OrdList FloatingBind,  -- any floats we pulled out
+                  Floats,                -- any floats we pulled out
                   [Demand])              -- remaining argument demands
 
     collect_args (App fun arg@(Type arg_ty)) depth
@@ -328,17 +464,18 @@ corePrepExprFloat env expr@(App _ _)
                                  splitFunTy_maybe fun_ty
          in
          corePrepArg env arg (mkDemTy ss1 arg_ty)      `thenUs` \ (fs, arg') ->
-         returnUs (App fun' arg', hd, res_ty, fs `appOL` floats, ss_rest)
+         returnUs (App fun' arg', hd, res_ty, fs `appendFloats` floats, ss_rest)
 
     collect_args (Var v) depth
        = fiddleCCall v `thenUs` \ v1 ->
          let v2 = lookupVarEnv env v1 `orElse` v1 in
-         returnUs (Var v2, (Var v2, depth), idType v2, nilOL, stricts)
+         returnUs (Var v2, (Var v2, depth), idType v2, emptyFloats, stricts)
        where
          stricts = case idNewStrictness v of
                        StrictSig (DmdType _ demands _)
-                           | depth >= length demands -> demands
-                           | otherwise               -> []
+                           | listLengthCmp demands depth /= GT -> demands
+                                   -- length demands <= depth
+                           | otherwise                         -> []
                -- If depth < length demands, then we have too few args to 
                -- satisfy strictness  info so we have to  ignore all the 
                -- strictness info, e.g. + (error "urk")
@@ -356,18 +493,21 @@ corePrepExprFloat env expr@(App _ _)
          returnUs (Note note fun', hd, fun_ty, floats, ss)
 
        -- non-variable fun, better let-bind it
+       -- ToDo: perhaps we can case-bind rather than let-bind this closure,
+       -- since it is sure to be evaluated.
     collect_args fun depth
        = corePrepExprFloat env fun                     `thenUs` \ (fun_floats, fun') ->
-         newVar ty (exprArity fun')                    `thenUs` \ fn_id ->
+         newVar ty                                     `thenUs` \ fn_id ->
           mkLocalNonRec fn_id onceDem fun_floats fun'  `thenUs` \ floats ->
          returnUs (Var fn_id, (Var fn_id, depth), ty, floats, [])
         where
          ty = exprType fun
 
-    ignore_note        InlineCall = True
-    ignore_note        InlineMe   = True
-    ignore_note        _other     = False
-       -- we don't ignore SCCs, since they require some code generation
+    ignore_note        (CoreNote _) = True 
+    ignore_note        InlineCall   = True
+    ignore_note        InlineMe     = True
+    ignore_note        _other       = False
+       -- We don't ignore SCCs, since they require some code generation
 
 ------------------------------------------------------------------------------
 -- Building the saturated syntax
@@ -389,58 +529,67 @@ maybeSaturate fn expr n_args ty
 -- Precipitating the floating bindings
 -- ---------------------------------------------------------------------------
 
-floatRhs :: TopLevelFlag -> Id
-        -> (OrdList FloatingBind, CoreExpr)    -- Rhs: let binds in body
-        -> UniqSM (OrdList FloatingBind,       -- Floats out of this bind
-                   CoreExpr)                   -- Final Rhs
+floatRhs :: TopLevelFlag -> RecFlag
+        -> Id
+        -> (Floats, CoreExpr)  -- Rhs: let binds in body
+        -> UniqSM (Floats,     -- Floats out of this bind
+                   CoreExpr)   -- Final Rhs
 
-floatRhs top_lvl bndr (floats, rhs)
+floatRhs top_lvl is_rec bndr (floats, rhs)
   | isTopLevel top_lvl || exprIsValue rhs,     -- Float to expose value or 
-    allLazy floats                             -- at top level
+    allLazy top_lvl is_rec floats              -- at top level
   =    -- Why the test for allLazy? 
        --      v = f (x `divInt#` y)
        -- we don't want to float the case, even if f has arity 2,
        -- because floating the case would make it evaluated too early
        --
        -- Finally, eta-expand the RHS, for the benefit of the code gen
-    etaExpandRhs bndr rhs      `thenUs` \ rhs' ->
-    returnUs (floats, rhs')
+    returnUs (floats, rhs)
     
   | otherwise
        -- Don't float; the RHS isn't a value
   = mkBinds floats rhs         `thenUs` \ rhs' ->
-    etaExpandRhs bndr rhs'     `thenUs` \ rhs'' ->
-    returnUs (nilOL, rhs'')
+    returnUs (emptyFloats, rhs')
 
 -- mkLocalNonRec is used only for *nested*, *non-recursive* bindings
-mkLocalNonRec :: Id  -> RhsDemand                      -- Lhs: id with demand
-             -> OrdList FloatingBind -> CoreExpr       -- Rhs: let binds in body
-             -> UniqSM (OrdList FloatingBind)
+mkLocalNonRec :: Id  -> RhsDemand      -- Lhs: id with demand
+             -> Floats -> CoreExpr     -- Rhs: let binds in body
+             -> UniqSM Floats
 
 mkLocalNonRec bndr dem floats rhs
-  |  isUnLiftedType (idType bndr) || isStrict dem 
-       -- It's a strict let, or the binder is unlifted,
-       -- so we definitely float all the bindings
+  | isUnLiftedType (idType bndr)
+       -- If this is an unlifted binding, we always make a case for it.
   = ASSERT( not (isUnboxedTupleType (idType bndr)) )
-    let                -- Don't make a case for a value binding,
+    let
+       float = FloatCase bndr rhs (exprOkForSpeculation rhs)
+    in
+    returnUs (addFloat floats float)
+
+  | isStrict dem 
+       -- It's a strict let so we definitely float all the bindings
+ = let         -- Don't make a case for a value binding,
                -- even if it's strict.  Otherwise we get
                --      case (\x -> e) of ...!
        float | exprIsValue rhs = FloatLet (NonRec bndr rhs)
              | otherwise       = FloatCase bndr rhs (exprOkForSpeculation rhs)
     in
-    returnUs (floats `snocOL` float)
+    returnUs (addFloat floats float)
 
   | otherwise
-  = floatRhs NotTopLevel bndr (floats, rhs)    `thenUs` \ (floats', rhs') ->
-    returnUs (floats' `snocOL` FloatLet (NonRec bndr rhs'))
+  = floatRhs NotTopLevel NonRecursive bndr (floats, rhs)       `thenUs` \ (floats', rhs') ->
+    returnUs (addFloat floats' (FloatLet (NonRec bndr rhs')))
 
-mkBinds :: OrdList FloatingBind -> CoreExpr -> UniqSM CoreExpr
-mkBinds binds body 
+  where
+    bndr_ty     = idType bndr
+
+
+mkBinds :: Floats -> CoreExpr -> UniqSM CoreExpr
+mkBinds (Floats _ binds) body 
   | isNilOL binds = returnUs body
   | otherwise    = deLam body          `thenUs` \ body' ->
                    returnUs (foldrOL mk_bind body' binds)
   where
-    mk_bind (FloatCase bndr rhs _) body = mkCase rhs bndr [(DEFAULT, [], body)]
+    mk_bind (FloatCase bndr rhs _) body = Case rhs bndr [(DEFAULT, [], body)]
     mk_bind (FloatLet bind)        body = Let bind body
 
 etaExpandRhs bndr rhs
@@ -463,30 +612,53 @@ etaExpandRhs bndr rhs
        --    an SCC note - we're now careful in etaExpand to make sure the
        --    SCC is pushed inside any new lambdas that are generated.
        --
+       -- NB3: It's important to do eta expansion, and *then* ANF-ising
+       --              f = /\a -> g (h 3)      -- h has arity 2
+       -- If we ANF first we get
+       --              f = /\a -> let s = h 3 in g s
+       -- and now eta expansion gives
+       --              f = /\a -> \ y -> (let s = h 3 in g s) y
+       -- which is horrible.
+       -- Eta expanding first gives
+       --              f = /\a -> \y -> let s = h 3 in g s y
+       --
     getUniquesUs               `thenUs` \ us ->
-    returnUs (etaExpand (idArity bndr) us rhs (idType bndr))
+    returnUs (etaExpand arity us rhs (idType bndr))
+  where
+       -- For a GlobalId, take the Arity from the Id.
+       -- It was set in CoreTidy and must not change
+       -- For all others, just expand at will
+    arity | isGlobalId bndr = idArity bndr
+         | otherwise       = exprArity rhs
 
 -- ---------------------------------------------------------------------------
 -- Eliminate Lam as a non-rhs (STG doesn't have such a thing)
 -- We arrange that they only show up as the RHS of a let(rec)
 -- ---------------------------------------------------------------------------
 
-deLam :: CoreExpr -> UniqSM CoreExpr   
+deLam :: CoreExpr -> UniqSM CoreExpr
+deLam expr = 
+  deLamFloat expr   `thenUs` \ (floats, expr) ->
+  mkBinds floats expr
+
+
+deLamFloat :: CoreExpr -> UniqSM (Floats, CoreExpr)
 -- Remove top level lambdas by let-bindinig
 
-deLam (Note n expr)
+deLamFloat (Note n expr)
   =    -- You can get things like
        --      case e of { p -> coerce t (\s -> ...) }
-    deLam expr `thenUs` \ expr' ->
-    returnUs (Note n expr')
+    deLamFloat expr    `thenUs` \ (floats, expr') ->
+    returnUs (floats, Note n expr')
 
-deLam expr 
-  | null bndrs = returnUs expr
+deLamFloat expr 
+  | null bndrs = returnUs (emptyFloats, expr)
   | otherwise 
   = case tryEta bndrs body of
-      Just no_lam_result -> returnUs no_lam_result
-      Nothing           -> newVar (exprType expr) (exprArity expr) `thenUs` \ fn ->
-                           returnUs (Let (NonRec fn expr) (Var fn))
+      Just no_lam_result -> returnUs (emptyFloats, no_lam_result)
+      Nothing           -> newVar (exprType expr)      `thenUs` \ fn ->
+                           returnUs (unitFloat (FloatLet (NonRec fn expr)), 
+                                     Var fn)
   where
     (bndrs,body) = collectBinders expr
 
@@ -509,7 +681,7 @@ tryEta bndrs expr@(App _ _)
     n_remaining = length args - length bndrs
 
     ok bndr (Var arg) = bndr == arg
-    ok bndr other          = False
+    ok bndr other     = False
 
          -- we can't eta reduce something which must be saturated.
     ok_to_eta_reduce (Var f) = not (hasNoBinding f)
@@ -528,55 +700,6 @@ tryEta bndrs _ = Nothing
 
 
 -- -----------------------------------------------------------------------------
---     Do the seq and par transformation
--- -----------------------------------------------------------------------------
-
-Here we do two pre-codegen transformations:
-
-1.     case seq# a of {
-         0       -> seqError ...
-         DEFAULT -> rhs }
-  ==>
-       case a of { DEFAULT -> rhs }
-
-
-2.     case par# a of {
-         0       -> parError ...
-         DEFAULT -> rhs }
-  ==>
-       case par# a of {
-         DEFAULT -> rhs }
-
-NB:    seq# :: a -> Int#       -- Evaluate value and return anything
-       par# :: a -> Int#       -- Spark value and return anything
-
-These transformations can't be done earlier, or else we might
-think that the expression was strict in the variables in which 
-rhs is strict --- but that would defeat the purpose of seq and par.
-
-
-\begin{code}
-mkCase scrut@(Var fn `App` Type ty `App` arg) bndr alts@(deflt_alt@(DEFAULT,_,rhs) : con_alts)
-                       -- DEFAULT alt is always first
-  = case isPrimOpId_maybe fn of
-       Just ParOp -> Case scrut bndr     [deflt_alt]
-       Just SeqOp -> Case arg   new_bndr [deflt_alt]
-       other      -> Case scrut bndr alts
-  where
-       -- The binder shouldn't be used in the expression!
-    new_bndr = ASSERT2( not (bndr `elemVarSet` exprFreeVars rhs), ppr bndr )
-              setIdType bndr (exprType arg)
-       -- NB:  SeqOp :: forall a. a -> Int#
-       -- So bndr has type Int# 
-       -- But now we are going to scrutinise the SeqOp's argument directly,
-       -- so we must change the type of the case binder to match that
-       -- of the argument expression e.
-
-mkCase scrut bndr alts = Case scrut bndr alts
-\end{code}
-
-
--- -----------------------------------------------------------------------------
 -- Demands
 -- -----------------------------------------------------------------------------
 
@@ -590,26 +713,17 @@ mkDem :: Demand -> Bool -> RhsDemand
 mkDem strict once = RhsDemand (isStrictDmd strict) once
 
 mkDemTy :: Demand -> Type -> RhsDemand
-mkDemTy strict ty = RhsDemand (isStrictDmd strict) (isOnceTy ty)
-
-isOnceTy :: Type -> Bool
-isOnceTy ty
-  =
-#ifdef USMANY
-    opt_UsageSPOn &&  -- can't expect annotations if -fusagesp is off
-#endif
-    once
-  where
-    u = uaUTy ty
-    once | u `eqUsage` usOnce  = True
-         | u `eqUsage` usMany  = False
-         | isTyVarTy u                = False  -- if unknown at compile-time, is Top ie usMany
+mkDemTy strict ty = RhsDemand (isStrictDmd strict) 
+                             False {- For now -}
 
 bdrDem :: Id -> RhsDemand
-bdrDem id = mkDem (idNewDemandInfo id) (isOnceTy (idType id))
+bdrDem id = mkDem (idNewDemandInfo id)
+                 False {- For now -}
+
+-- safeDem :: RhsDemand
+-- safeDem = RhsDemand False False  -- always safe to use this
 
-safeDem, onceDem :: RhsDemand
-safeDem = RhsDemand False False  -- always safe to use this
+onceDem :: RhsDemand
 onceDem = RhsDemand False True   -- used at most once
 \end{code}
 
@@ -632,16 +746,19 @@ cloneBndrs env bs = mapAccumLUs cloneBndr env bs
 
 cloneBndr  :: CloneEnv -> Var -> UniqSM (CloneEnv, Var)
 cloneBndr env bndr
-  | isGlobalId bndr            -- Top level things, which we don't want
-  = returnUs (env, bndr)       -- to clone, have become GlobalIds by now
-  
-  | otherwise
+  | isLocalId bndr
   = getUniqueUs   `thenUs` \ uniq ->
     let
        bndr' = setVarUnique bndr uniq
     in
     returnUs (extendVarEnv env bndr bndr', bndr')
 
+  | otherwise  -- Top level things, which we don't want
+               -- to clone, have become GlobalIds by now
+               -- And we don't clone tyvars
+  = returnUs (env, bndr)
+  
+
 ------------------------------------------------------------------------------
 -- Cloning ccall Ids; each must have a unique name,
 -- to give the code generator a handle to hang it on
@@ -657,12 +774,9 @@ fiddleCCall id
 -- Generating new binders
 -- ---------------------------------------------------------------------------
 
-newVar :: Type -> Arity -> UniqSM Id
--- We're creating a new let binder, and we must give
--- it the right arity for the benefit of the code generator.
-newVar ty arity
+newVar :: Type -> UniqSM Id
+newVar ty
  = seqType ty                  `seq`
    getUniqueUs                 `thenUs` \ uniq ->
-   returnUs (mkSysLocal SLIT("sat") uniq ty
-            `setIdArity` arity)
+   returnUs (mkSysLocal FSLIT("sat") uniq ty)
 \end{code}