[project @ 1996-07-25 20:43:49 by partain]
[ghc-hetmet.git] / ghc / compiler / simplCore / Simplify.lhs
index 7c21e22..2141e07 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The AQUA Project, Glasgow University, 1993-1995
+% (c) The AQUA Project, Glasgow University, 1993-1996
 %
 \section[Simplify]{The main module of the simplifier}
 
@@ -8,36 +8,42 @@
 
 module Simplify ( simplTopBinds, simplExpr, simplBind ) where
 
-import Pretty          -- these are for debugging only
-import Outputable
+IMP_Ubiq(){-uitous-}
+IMPORT_DELOOPER(SmplLoop)              -- paranoia checking
+IMPORT_1_3(List(partition))
 
-import SimplMonad
-import SimplEnv
-import TaggedCore
-import PlainCore
-
-import AbsPrel         ( getPrimOpResultInfo, PrimOpResultInfo(..),
-                         primOpOkForSpeculation, PrimOp(..), PrimKind,
-                         realWorldStateTy
-                         IF_ATTACK_PRAGMAS(COMMA realWorldTy)
-                         IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
-                         IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
-                       )
-import AbsUniType      ( getUniDataTyCon_maybe, mkTyVarTy, applyTy,
-                         splitTyArgs, splitTypeWithDictsAsArgs,
-                         maybeUnpackFunTy, isPrimType
-                       )
-import BasicLit                ( isNoRepLit, BasicLit(..) )
 import BinderInfo
 import CmdLineOpts     ( SimplifierSwitch(..) )
 import ConFold         ( completePrim )
-import Id
-import IdInfo
-import Maybes          ( Maybe(..), catMaybes, maybeToBool )
-import SimplCase
-import SimplUtils
+import CoreUnfold      ( Unfolding, SimpleUnfolding, mkFormSummary, FormSummary(..) )
+import CostCentre      ( isSccCountCostCentre, cmpCostCentre )
+import CoreSyn
+import CoreUtils       ( coreExprType, nonErrorRHSs, maybeErrorApp,
+                         unTagBinders, squashableDictishCcExpr
+                       )
+import Id              ( idType, idWantsToBeINLINEd,
+                         externallyVisibleId,
+                         getIdDemandInfo, addIdDemandInfo,
+                         GenId{-instance NamedThing-}
+                       )
+import IdInfo          ( willBeDemanded, DemandInfo )
+import Literal         ( isNoRepLit )
+import Maybes          ( maybeToBool )
+--import Name          ( isExported )
+import PprStyle                ( PprStyle(..) )
+import PprType         ( GenType{-instance Outputable-} )
+import Pretty          ( ppAbove )
+import PrimOp          ( primOpOkForSpeculation, PrimOp(..) )
+import SimplCase       ( simplCase, bindLargeRhs )
+import SimplEnv
+import SimplMonad
 import SimplVar                ( completeVar )
-import Util
+import SimplUtils
+import Type            ( mkTyVarTy, mkTyVarTys, mkAppTy,
+                         splitFunTy, getFunTy_maybe, eqTy
+                       )
+import TysWiredIn      ( realWorldStateTy )
+import Util            ( isSingleton, zipEqual, panic, pprPanic, assertPanic )
 \end{code}
 
 The controlling flags, and what they do
@@ -48,7 +54,7 @@ passes:
 -fsimplify             = run the simplifier
 -ffloat-inwards                = runs the float lets inwards pass
 -ffloat                        = runs the full laziness pass
-                          (ToDo: rename to -ffull-laziness)
+                         (ToDo: rename to -ffull-laziness)
 -fupdate-analysis      = runs update analyser
 -fstrictness           = runs strictness analyser
 -fsaturate-apps                = saturates applications (eta expansion)
@@ -56,20 +62,20 @@ passes:
 options:
 -------
 -ffloat-past-lambda    = OK to do full laziness.
-                          (ToDo: remove, as the full laziness pass is
-                                 useless without this flag, therefore
-                                 it is unnecessary. Just -ffull-laziness
-                                 should be kept.)
+                         (ToDo: remove, as the full laziness pass is
+                                useless without this flag, therefore
+                                it is unnecessary. Just -ffull-laziness
+                                should be kept.)
 
 -ffloat-lets-ok                = OK to float lets out of lets if the enclosing
-                          let is strict or if the floating will expose
-                          a WHNF [simplifier].
+                         let is strict or if the floating will expose
+                         a WHNF [simplifier].
 
--ffloat-primops-ok     = OK to float out of lets cases whose scrutinee 
-                          is a primop that cannot fail [simplifier].
+-ffloat-primops-ok     = OK to float out of lets cases whose scrutinee
+                         is a primop that cannot fail [simplifier].
 
 -fcode-duplication-ok  = allows the previous option to work on cases with
-                          multiple branches [simplifier].
+                         multiple branches [simplifier].
 
 -flet-to-case          = does let-to-case transformation [simplifier].
 
@@ -102,9 +108,9 @@ binding altogether.
 
 2.  Conditional.  In all other situations, the simplifer simplifies
 the RHS anyway, and keeps the new binding.  It also binds the new
-(cloned) variable to a ``suitable'' UnfoldingDetails in the UnfoldEnv.
+(cloned) variable to a ``suitable'' Unfolding in the UnfoldEnv.
 
-Here, ``suitable'' might mean NoUnfoldingDetails (if the occurrence
+Here, ``suitable'' might mean NoUnfolding (if the occurrence
 info is ManyOcc and the RHS is not a manifest HNF, or UnfoldAlways (if
 the variable has an INLINE pragma on it).  The idea is that anything
 in the UnfoldEnv is safe to use, but also has an enclosing binding if
@@ -113,7 +119,7 @@ you decide not to use it.
 Head normal forms
 ~~~~~~~~~~~~~~~~~
 We *never* put a non-HNF unfolding in the UnfoldEnv except in the
-INLINE-pragma case.  
+INLINE-pragma case.
 
 At one time I thought it would be OK to put non-HNF unfoldings in for
 variables which occur only once [if they got inlined at that
@@ -124,12 +130,12 @@ would occur].   But consider:
            f = \y -> ...y...y...y...
        in f x
 @
-Now, it seems that @x@ appears only once, but even so it is NOT safe to put @x@
-in the UnfoldEnv, because @f@ will be inlined, and will duplicate the references to
-@x@.  
+Now, it seems that @x@ appears only once, but even so it is NOT safe
+to put @x@ in the UnfoldEnv, because @f@ will be inlined, and will
+duplicate the references to @x@.
 
-Becuase of this, the "unconditional-inline" mechanism above is the only way
-in which non-HNFs can get inlined.
+Because of this, the "unconditional-inline" mechanism above is the
+only way in which non-HNFs can get inlined.
 
 INLINE pragmas
 ~~~~~~~~~~~~~~
@@ -151,7 +157,7 @@ because then we'd duplicate BIG when we inline'd y.  (Exception:
 things in the UnfoldEnv with UnfoldAlways flags, which originated in
 other INLINE pragmas.)
 
-So, we clean out the UnfoldEnv of all GeneralForm inlinings before
+So, we clean out the UnfoldEnv of all SimpleUnfolding inlinings before
 going into such an RHS.
 
 What about imports?  They don't really matter much because we only
@@ -185,53 +191,28 @@ simplTopBinds env [] = returnSmpl []
 
 -- Dead code is now discarded by the occurrence analyser,
 
-simplTopBinds env (CoNonRec binder@(in_id, occ_info) rhs : binds)
-  | inlineUnconditionally ok_to_dup_code occ_info
-  = --pprTrace "simplTopBinds (inline):" (ppr PprDebug in_id) (
-    let
-       new_env = extendIdEnvWithInlining env env binder rhs
-    in
-    simplTopBinds new_env binds
-    --)
-  where
-    ok_to_dup_code = switchIsSet env SimplOkToDupCode
-
-simplTopBinds env (CoNonRec binder@(in_id,occ_info) rhs : binds)
+simplTopBinds env (NonRec binder@(in_id,occ_info) rhs : binds)
   =    -- No cloning necessary at top level
        -- Process the binding
-    simplRhsExpr env binder rhs                `thenSmpl` \ rhs' ->
-    let
-       new_env = case rhs' of
-        CoVar var                        -> extendIdEnvWithAtom env binder (CoVarAtom var)
-         CoLit lit | not (isNoRepLit lit) -> extendIdEnvWithAtom env binder (CoLitAtom lit)
-         other                           -> extendUnfoldEnvGivenRhs env binder in_id rhs'
-    in
-    --pprTrace "simplTopBinds (nonrec):" (ppCat [ppr PprDebug in_id, ppr PprDebug rhs']) (
+    simplRhsExpr env binder rhs                `thenSmpl` \ rhs' ->
+    completeNonRec env binder in_id rhs'       `thenSmpl` \ (new_env, binds1') ->
 
        -- Process the other bindings
-    simplTopBinds new_env binds        `thenSmpl` \ binds' ->
+    simplTopBinds new_env binds        `thenSmpl` \ binds2' ->
 
        -- Glue together and return ...
-       -- We leave it to susequent occurrence analysis to throw away 
-       -- an unused atom binding. This localises the decision about
-       -- discarding top-level bindings.
-    returnSmpl (CoNonRec in_id rhs' : binds')
-    --)
-
-simplTopBinds env (CoRec pairs : binds)
-  = simplRecursiveGroup env triples    `thenSmpl` \ (bind', new_env) ->
+    returnSmpl (binds1' ++ binds2')
 
-    --pprTrace "simplTopBinds (rec):" (ppCat [ppr PprDebug bind']) (
+simplTopBinds env (Rec pairs : binds)
+  = simplRecursiveGroup env ids pairs  `thenSmpl` \ (bind', new_env) ->
 
        -- Process the other bindings
     simplTopBinds new_env binds                `thenSmpl` \ binds' ->
 
        -- Glue together and return
     returnSmpl (bind' : binds')
-    --)
   where
-    triples = [(id, (binder, rhs)) | (binder@(id,_), rhs) <- pairs]
-               -- No cloning necessary at top level
+    ids = [id | (binder@(id,_), rhs) <- pairs] -- No cloning necessary at top level
 \end{code}
 
 %************************************************************************
@@ -240,11 +221,11 @@ simplTopBinds env (CoRec pairs : binds)
 %*                                                                     *
 %************************************************************************
 
-       
-\begin{code} 
+
+\begin{code}
 simplExpr :: SimplEnv
          -> InExpr -> [OutArg]
-         -> SmplM OutExpr 
+         -> SmplM OutExpr
 \end{code}
 
 The expression returned has the same meaning as the input expression
@@ -253,63 +234,51 @@ applied to the specified arguments.
 
 Variables
 ~~~~~~~~~
-Check if there's a macro-expansion, and if so rattle on.  Otherwise
-do the more sophisticated stuff.
+Check if there's a macro-expansion, and if so rattle on.  Otherwise do
+the more sophisticated stuff.
 
 \begin{code}
-simplExpr env (CoVar v) args
-  = --pprTrace "simplExpr:Var:" (ppr PprDebug v) (
-    case lookupId env v of
-      Nothing -> let
-                       new_v = simplTyInId env v
-                in
-                completeVar env new_v args
-
-      Just info ->
-       case info of
-         ItsAnAtom (CoLitAtom lit)     -- A boring old literal
-                       -- Paranoia check for args empty
-           ->  case args of
-                 []    -> returnSmpl (CoLit lit)
-                 other -> panic "simplExpr:coVar"
-
-         ItsAnAtom (CoVarAtom var)     -- More interesting!  An id!
-                                       -- No need to substitute the type env here,
-                                       -- because we already have!
-           -> completeVar env var args 
-               
-         InlineIt id_env ty_env in_expr        -- A macro-expansion
-           -> simplExpr (replaceInEnvs env (ty_env, id_env)) in_expr args
-    --)
+simplExpr env (Var v) args
+  = case (lookupId env v) of
+      LitArg lit               -- A boring old literal
+       -> ASSERT( null args )
+          returnSmpl (Lit lit)
+
+      VarArg var       -- More interesting!  An id!
+       -> completeVar env var args
+                               -- Either Id is in the local envt, or it's a global.
+                               -- In either case we don't need to apply the type
+                               -- environment to it.
 \end{code}
 
 Literals
-~~~~~~~~~
+~~~~~~~~
 
 \begin{code}
-simplExpr env (CoLit l) [] = returnSmpl (CoLit l)
-simplExpr env (CoLit l) _  = panic "simplExpr:CoLit with argument"
+simplExpr env (Lit l) [] = returnSmpl (Lit l)
+#ifdef DEBUG
+simplExpr env (Lit l) _  = panic "simplExpr:Lit with argument"
+#endif
 \end{code}
 
-Primitive applications are simple.  
+Primitive applications are simple.
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
-NB: CoPrim expects an empty argument list! (Because it should be
+NB: Prim expects an empty argument list! (Because it should be
 saturated and not higher-order. ADR)
 
-\begin{code} 
-simplExpr env (CoPrim op tys prim_args) args
+\begin{code}
+simplExpr env (Prim op prim_args) args
   = ASSERT (null args)
     let
-       tys'       = [simplTy   env ty       | ty       <- tys]
-       prim_args' = [simplAtom env prim_arg | prim_arg <- prim_args]
+       prim_args' = [simplArg env prim_arg | prim_arg <- prim_args]
        op'        = simpl_op op
     in
-    completePrim env op' tys' prim_args'
+    completePrim env op' prim_args'
   where
     -- PrimOps just need any types in them renamed.
 
-    simpl_op (CCallOp label is_asm may_gc arg_tys result_ty) 
+    simpl_op (CCallOp label is_asm may_gc arg_tys result_ty)
       = let
            arg_tys'    = map (simplTy env) arg_tys
            result_ty'  = simplTy env result_ty
@@ -319,31 +288,25 @@ simplExpr env (CoPrim op tys prim_args) args
     simpl_op other_op = other_op
 \end{code}
 
-Constructor applications 
-~~~~~~~~~~~~~~~~~~~~~~~~ 
+Constructor applications
+~~~~~~~~~~~~~~~~~~~~~~~~
 Nothing to try here.  We only reuse constructors when they appear as the
 rhs of a let binding (see completeLetBinding).
 
 \begin{code}
-simplExpr env (CoCon con tys con_args) args
+simplExpr env (Con con con_args) args
   = ASSERT( null args )
-    returnSmpl (CoCon con tys' con_args')
-  where
-    con_args' = [simplAtom env con_arg | con_arg <- con_args]
-    tys'      = [simplTy   env ty      | ty <- tys]
+    returnSmpl (Con con [simplArg env con_arg | con_arg <- con_args])
 \end{code}
 
 
-Applications are easy too: 
-~~~~~~~~~~~~~~~~~~~~~~~~~~ 
+Applications are easy too:
+~~~~~~~~~~~~~~~~~~~~~~~~~~
 Just stuff 'em in the arg stack
 
-\begin{code} 
-simplExpr env (CoApp fun arg) args
-  = simplExpr env fun (ValArg (simplAtom env arg) : args)
-
-simplExpr env (CoTyApp fun ty) args
-  = simplExpr env fun (TypeArg (simplTy env ty) : args)
+\begin{code}
+simplExpr env (App fun arg) args
+  = simplExpr env fun (simplArg env arg : args)
 \end{code}
 
 Type lambdas
@@ -351,21 +314,18 @@ Type lambdas
 
 We only eta-reduce a type lambda if all type arguments in the body can
 be eta-reduced. This requires us to collect up all tyvar parameters so
-we can pass them all to @mkCoTyLamTryingEta@.
+we can pass them all to @mkTyLamTryingEta@.
 
-\begin{code} 
-simplExpr env (CoTyLam tyvar body) (TypeArg ty : args)
-  = ASSERT(not (isPrimType ty))
-    let
-       new_env = extendTyEnv env tyvar ty
-    in
+\begin{code}
+simplExpr env (Lam (TyBinder tyvar) body) (TyArg ty : args)
+  = -- ASSERT(not (isPrimType ty))
     tick TyBetaReduction       `thenSmpl_`
-    simplExpr new_env body args
+    simplExpr (extendTyEnv env tyvar ty) body args
 
-simplExpr env tylam@(CoTyLam tyvar body) []
-  = do_tylambdas env [] tylam 
+simplExpr env tylam@(Lam (TyBinder tyvar) body) []
+  = do_tylambdas env [] tylam
   where
-    do_tylambdas env tyvars' (CoTyLam tyvar body)
+    do_tylambdas env tyvars' (Lam (TyBinder tyvar) body)
       =          -- Clone the type variable
        cloneTyVarSmpl tyvar            `thenSmpl` \ tyvar' ->
        let
@@ -377,137 +337,131 @@ simplExpr env tylam@(CoTyLam tyvar body) []
       =        simplExpr env body []           `thenSmpl` \ body' ->
        returnSmpl (
           (if switchIsSet env SimplDoEtaReduction
-          then mkCoTyLamTryingEta
-          else mkCoTyLam) (reverse tyvars')  body'
+          then mkTyLamTryingEta
+          else mkTyLam) (reverse tyvars')  body'
        )
 
-simplExpr env (CoTyLam tyvar body) (ValArg _ : _)
-  = panic "simplExpr:CoTyLam ValArg" 
+#ifdef DEBUG
+simplExpr env (Lam (TyBinder _) _) (_ : _)
+  = panic "simplExpr:TyLam with non-TyArg"
+#endif
 \end{code}
 
 
 Ordinary lambdas
 ~~~~~~~~~~~~~~~~
 
-\begin{code}
-simplExpr env (CoLam binders body) args
-  | null leftover_binders
-  =    -- The lambda is saturated (or over-saturated)
-    tick BetaReduction `thenSmpl_`
-    simplExpr env_for_enough_args body leftover_args
-
-  | otherwise
-  =    -- Too few args to saturate the lambda
-    ASSERT( null leftover_args )
+There's a complication with lambdas that aren't saturated.
+Suppose we have:
 
-    (if not (null args) -- ah, we must've gotten rid of some...
-     then tick BetaReduction
-     else returnSmpl (panic "BetaReduction")
-    ) `thenSmpl_`
+       (\x. \y. ...x...)
 
-    simplLam env_for_too_few_args leftover_binders body 
-            0 {- Guaranteed applied to at least 0 args! -}
+If we did nothing, x is used inside the \y, so would be marked
+as dangerous to dup.  But in the common case where the abstraction
+is applied to two arguments this is over-pessimistic.
+So instead we don't take account of the \y when dealing with x's usage;
+instead, the simplifier is careful when partially applying lambdas.
 
+\begin{code}
+simplExpr env expr@(Lam (ValBinder binder) body) orig_args
+  = go 0 env expr orig_args
   where
-    (binder_args_pairs, leftover_binders, leftover_args) = collect_val_args binders args
-
-    env_for_enough_args  = extendIdEnvWithAtomList env binder_args_pairs
-
-    env_for_too_few_args = extendIdEnvWithAtomList env zapped_binder_args_pairs
-
-       -- Since there aren't enough args the binders we are cancelling with
-       -- the args supplied are, in effect, ocurring inside a lambda.
-       -- So we modify their occurrence info to reflect this fact.
-       -- Example:     (\ x y z -> e) p q
-       --          ==> (\z -> e[p/x, q/y])
-       --      but we should behave as if x and y are marked "inside lambda".
-       -- The occurrence analyser does not mark them so itself because then we
-       -- do badly on the very common case of saturated lambdas applications:
-       --              (\ x y z -> e) p q r
-       --          ==> e[p/x, q/y, r/z]
-       --
-    zapped_binder_args_pairs = [ ((id, markDangerousToDup occ_info), arg) 
-                              | ((id, occ_info), arg) <- binder_args_pairs ]
-
-    collect_val_args :: [InBinder]     -- Binders
-                    -> [OutArg]        -- Arguments
-                    -> ([(InBinder,OutAtom)],  -- Binder,arg pairs
-                         [InBinder],           -- Leftover binders
-                         [OutArg])             -- Leftover args
-       
-       -- collect_val_args strips off the leading ValArgs from
-       -- the current arg list, returning them along with the
-       -- depleted list
-    collect_val_args []      args = ([], [], args)
-    collect_val_args binders []   = ([], binders, [])
-    collect_val_args (binder:binders) (ValArg val_arg : args)
-       = ((binder,val_arg):rest_pairs, leftover_binders, leftover_args)
-       where
-         (rest_pairs, leftover_binders, leftover_args) = collect_val_args binders args
-
-    collect_val_args (binder:binders) (other_val_arg : args) = panic "collect_val_args"
-               -- TypeArg should never meet a CoLam
+    go n env (Lam (ValBinder binder) body) (val_arg : args)
+      | isValArg val_arg               -- The lambda has an argument
+      = tick BetaReduction     `thenSmpl_`
+        go (n+1) (extendIdEnvWithAtom env binder val_arg) body args
+
+    go n env expr@(Lam (ValBinder binder) body) args
+       -- The lambda is un-saturated, so we must zap the occurrence info
+       -- on the arguments we've already beta-reduced into the body of the lambda
+      = ASSERT( null args )    -- Value lambda must match value argument!
+        let
+           new_env = markDangerousOccs env (take n orig_args)
+        in
+        simplValLam new_env expr 0 {- Guaranteed applied to at least 0 args! -}
+
+    go n env non_val_lam_expr args             -- The lambda had enough arguments
+      = simplExpr env non_val_lam_expr args
 \end{code}
 
 
-Let expressions 
+Let expressions
 ~~~~~~~~~~~~~~~
 
-\begin{code}   
-simplExpr env (CoLet bind body) args
-  = simplBind env bind (\env -> simplExpr env body args) (computeResultType env body args)
+\begin{code}
+simplExpr env (Let bind body) args
+  = simplBind env bind (\env -> simplExpr env body args)
+                      (computeResultType env body args)
 \end{code}
 
-Case expressions 
+Case expressions
 ~~~~~~~~~~~~~~~~
 
 \begin{code}
-simplExpr env expr@(CoCase scrut alts) args
+simplExpr env expr@(Case scrut alts) args
   = simplCase env scrut alts (\env rhs -> simplExpr env rhs args)
                             (computeResultType env expr args)
 \end{code}
 
 
-Set-cost-centre 
+Coercions
+~~~~~~~~~
+\begin{code}
+simplExpr env (Coerce coercion ty body) args
+  = simplCoerce env coercion ty body args 
+\end{code}
+
+
+Set-cost-centre
 ~~~~~~~~~~~~~~~
 
-A special case we do:
-\begin{verbatim}
-       scc "foo" (\x -> e)  ===>   \x -> scc "foo" e
-\end{verbatim}
-Simon thinks it's OK, at least for lexical scoping; and it makes
-interfaces change less (arities).
+1) Eliminating nested sccs ...
+We must be careful to maintain the scc counts ...
 
 \begin{code}
-simplExpr env (CoSCC cc (CoLam binders body)) args
-  = simplExpr env (CoLam binders (CoSCC cc body)) args
-
-simplExpr env (CoSCC cc (CoTyLam tyvar body)) args
-  = simplExpr env (CoTyLam tyvar (CoSCC cc body)) args
+simplExpr env (SCC cc1 (SCC cc2 expr)) args
+  | not (isSccCountCostCentre cc2) && case cmpCostCentre cc1 cc2 of { EQ_ -> True; _ -> False }
+       -- eliminate inner scc if no call counts and same cc as outer
+  = simplExpr env (SCC cc1 expr) args
+
+  | not (isSccCountCostCentre cc2) && not (isSccCountCostCentre cc1)
+       -- eliminate outer scc if no call counts associated with either ccs
+  = simplExpr env (SCC cc2 expr) args
 \end{code}
 
-Some other slightly turgid SCC tidying-up cases:
+2) Moving sccs inside lambdas ...
+  
 \begin{code}
-simplExpr env (CoSCC cc1 expr@(CoSCC _ _)) args
-  = simplExpr env expr args
-    -- the outer _scc_ serves no purpose 
+simplExpr env (SCC cc (Lam binder@(ValBinder _) body)) args
+  | not (isSccCountCostCentre cc)
+       -- move scc inside lambda only if no call counts
+  = simplExpr env (Lam binder (SCC cc body)) args
+
+simplExpr env (SCC cc (Lam binder body)) args
+       -- always ok to move scc inside type/usage lambda
+  = simplExpr env (Lam binder (SCC cc body)) args
+\end{code}
 
-simplExpr env (CoSCC cc expr) args
+3) Eliminating dict sccs ...
+
+\begin{code}
+simplExpr env (SCC cc expr) args
   | squashableDictishCcExpr cc expr
+       -- eliminate dict cc if trivial dict expression
   = simplExpr env expr args
-    -- the DICT-ish CC is no longer serving any purpose
 \end{code}
 
-NB: for other set-cost-centre we move arguments inside the body.
-ToDo: check with Patrick that this is ok.
+4) Moving arguments inside the body of an scc ...
+This moves the cost of doing the application inside the scc
+(which may include the cost of extracting methods etc)
 
 \begin{code}
-simplExpr env (CoSCC cost_centre body) args
+simplExpr env (SCC cost_centre body) args
   = let
-       new_env = setEnclosingCC env (EnclosingCC cost_centre)
+       new_env = setEnclosingCC env cost_centre
     in
     simplExpr new_env body args                `thenSmpl` \ body' ->
-    returnSmpl (CoSCC cost_centre body') 
+    returnSmpl (SCC cost_centre body')
 \end{code}
 
 %************************************************************************
@@ -529,49 +483,68 @@ it transforms the rhs to
 This is a Very Good Thing!
 
 \begin{code}
-simplRhsExpr 
+simplRhsExpr
        :: SimplEnv
        -> InBinder
        -> InExpr
-       -> SmplM OutExpr 
+       -> SmplM OutExpr
 
-simplRhsExpr env binder@(id,occ_info) rhs 
+simplRhsExpr env binder@(id,occ_info) rhs
   | dont_eta_expand rhs
   = simplExpr rhs_env rhs []
 
   | otherwise  -- Have a go at eta expansion
   =    -- Deal with the big lambda part
+    ASSERT( null uvars )       -- For now
+
     mapSmpl cloneTyVarSmpl tyvars                      `thenSmpl` \ tyvars' ->
     let
-       lam_env  = extendTyEnvList rhs_env (tyvars `zip` (map mkTyVarTy tyvars'))
+       lam_env  = extendTyEnvList rhs_env (zipEqual "simplRhsExpr" tyvars (mkTyVarTys tyvars'))
     in
        -- Deal with the little lambda part
-       -- Note that we call simplLam even if there are no binders, in case
-       -- it can do arity expansion.
-    simplLam lam_env binders body min_no_of_args       `thenSmpl` \ lambda' ->
+       -- Note that we call simplLam even if there are no binders,
+       -- in case it can do arity expansion.
+    simplValLam lam_env body (getBinderInfoArity occ_info)     `thenSmpl` \ lambda' ->
 
        -- Put it back together
     returnSmpl (
        (if switchIsSet env SimplDoEtaReduction
-       then mkCoTyLamTryingEta
-       else mkCoTyLam) tyvars' lambda'
+       then mkTyLamTryingEta
+       else mkTyLam) tyvars' lambda'
     )
   where
-       -- Note from ANDY:
-       -- If you say {-# INLINE #-} then you get what's coming to you;
-       -- you are saying inline the rhs, please.
-       -- we might want a {-# INLINE UNSIMPLIFIED #-} option.
-    rhs_env | simplIdWantsToBeINLINEd id env = filterUnfoldEnvForInlines env
-           | otherwise                      = env
-       
-    (tyvars, binders, body) = digForLambdas rhs
 
-    min_no_of_args | not (null binders)                        &&      -- It's not a thunk
-                    switchIsSet env SimplDoArityExpand         -- Arity expansion on
-                  = getBinderInfoArity occ_info - length binders
+    rhs_env | not (switchIsSet env IgnoreINLINEPragma) &&
+             idWantsToBeINLINEd id
+           = switchOffInlining env
+           | otherwise 
+            = env
+
+       -- Switch off all inlining in the RHS of things that have an INLINE pragma.
+       -- They are going to be inlined wherever they are used, and then all the
+       -- inlining will take effect.  Meanwhile, there isn't
+       -- much point in doing anything to the as-yet-un-INLINEd rhs.
+       -- It's very important to switch off inlining!  Consider:
+       --
+       -- let f = \pq -> BIG
+       -- in
+       -- let g = \y -> f y y
+       --     {-# INLINE g #-}
+       -- in ...g...g...g...g...g...
+       --
+       -- Now, if that's the ONLY occurrence of f, it will be inlined inside g,
+       -- and thence copied multiple times when g is inlined.
+
+       -- Andy disagrees! Example:
+       --      all xs = foldr (&&) True xs
+       --      any p = all . map p  {-# INLINE any #-}
+       --
+       -- Problem: any won't get deforested, and so if it's exported and
+       -- the importer doesn't use the inlining, (eg passes it as an arg)
+       -- then we won't get deforestation at all.
+       -- We havn't solved this problem yet!
 
-                  | otherwise  -- Not a thunk
-                  = 0          -- Play safe!
+    (uvars, tyvars, body) = collectUsageAndTyBinders rhs
 
        -- dont_eta_expand prevents eta expansion in silly situations.
        -- For example, consider the defn
@@ -580,18 +553,20 @@ simplRhsExpr env binder@(id,occ_info) rhs
        -- get eta-reduced back to y.  Furthermore, if this was a top level defn,
        -- and x was exported, then the defn won't be eliminated, so this
        -- silly expand/reduce cycle will happen every time, which makes the
-       -- simplifier loop!. 
+       -- simplifier loop!.
        -- The solution is to not even try eta expansion unless the rhs looks
-       -- non-trivial.  
-    dont_eta_expand (CoLit _)     = True
-    dont_eta_expand (CoVar _)     = True
-    dont_eta_expand (CoTyApp f _) = dont_eta_expand f
-    dont_eta_expand (CoTyLam _ b) = dont_eta_expand b
-    dont_eta_expand (CoCon _ _ _) = True
-    dont_eta_expand _            = False
+       -- non-trivial.
+    dont_eta_expand (Lit _)     = True
+    dont_eta_expand (Var _)     = True
+    dont_eta_expand (Con _ _)   = True
+    dont_eta_expand (App f a)
+      | notValArg    a         = dont_eta_expand f
+    dont_eta_expand (Lam x b)
+      | notValBinder x         = dont_eta_expand b
+    dont_eta_expand _          = False
 \end{code}
 
-               
+
 %************************************************************************
 %*                                                                     *
 \subsection{Simplify a lambda abstraction}
@@ -602,10 +577,11 @@ Simplify (\binders -> body) trying eta expansion and reduction, given that
 the abstraction will always be applied to at least min_no_of_args.
 
 \begin{code}
-simplLam env binders body min_no_of_args
+simplValLam env expr min_no_of_args
   | not (switchIsSet env SimplDoLambdaEtaExpansion) || -- Bale out if eta expansion off
+    null binders                                   ||  -- or it's a thunk
     null potential_extra_binder_tys                ||  -- or ain't a function
-    no_of_extra_binders == 0                           -- or no extra binders needed
+    no_of_extra_binders <= 0                           -- or no extra binders needed
   = cloneIds env binders               `thenSmpl` \ binders' ->
     let
        new_env = extendIdEnvWithClones env binders binders'
@@ -613,8 +589,8 @@ simplLam env binders body min_no_of_args
     simplExpr new_env body []          `thenSmpl` \ body' ->
     returnSmpl (
       (if switchIsSet new_env SimplDoEtaReduction
-       then mkCoLamTryingEta
-       else mkCoLam) binders' body'
+       then mkValLamTryingEta
+       else mkValLam) binders' body'
     )
 
   | otherwise                          -- Eta expansion possible
@@ -623,18 +599,19 @@ simplLam env binders body min_no_of_args
     let
        new_env = extendIdEnvWithClones env binders binders'
     in
-    newIds extra_binder_tys                                            `thenSmpl` \ extra_binders' ->
-    simplExpr new_env body (map (ValArg.CoVarAtom) extra_binders')     `thenSmpl` \ body' ->
+    newIds extra_binder_tys                            `thenSmpl` \ extra_binders' ->
+    simplExpr new_env body (map VarArg extra_binders') `thenSmpl` \ body' ->
     returnSmpl (
       (if switchIsSet new_env SimplDoEtaReduction
-       then mkCoLamTryingEta
-       else mkCoLam) (binders' ++ extra_binders') body'
+       then mkValLamTryingEta
+       else mkValLam) (binders' ++ extra_binders') body'
     )
 
   where
-    (potential_extra_binder_tys, res_ty) 
-       = splitTyArgs (simplTy env (typeOfCoreExpr (unTagBinders body)))
-       -- Note: it's possible that simplLam will be applied to something
+    (binders,body) = collectValBinders expr
+    (potential_extra_binder_tys, res_ty)
+       = splitFunTy (simplTy env (coreExprType (unTagBinders body)))
+       -- Note: it's possible that simplValLam will be applied to something
        -- with a forall type.  Eg when being applied to the rhs of
        --              let x = wurble
        -- where wurble has a forall-type, but no big lambdas at the top.
@@ -644,7 +621,7 @@ simplLam env binders body min_no_of_args
 
     no_of_extra_binders =      -- First, use the info about how many args it's
                                -- always applied to in its scope
-                          min_no_of_args
+                          (min_no_of_args - length binders)
 
                                -- Next, try seeing if there's a lambda hidden inside
                                -- something cheap
@@ -656,9 +633,40 @@ simplLam env binders body min_no_of_args
                                -- but usually doesn't
                           `max`
                           case potential_extra_binder_tys of
-                               [ty] | ty == realWorldStateTy -> 1
-                               other                         -> 0
+                               [ty] | ty `eqTy` realWorldStateTy -> 1
+                               other                             -> 0
+
+\end{code}
+
+
+
+%************************************************************************
+%*                                                                     *
+\subsection[Simplify-coerce]{Coerce expressions}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+-- (coerce (case s of p -> r)) args ==> case s of p -> (coerce r) args
+simplCoerce env coercion ty expr@(Case scrut alts) args
+  = simplCase env scrut alts (\env rhs -> simplCoerce env coercion ty rhs args)
+                            (computeResultType env expr args)
+
+-- (coerce (let defns in b)) args  ==> let defns' in (coerce b) args
+simplCoerce env coercion ty (Let bind body) args
+  = simplBind env bind (\env -> simplCoerce env coercion ty body args)
+                      (computeResultType env body args)
 
+-- Default case
+simplCoerce env coercion ty expr args
+  = simplExpr env expr []      `thenSmpl` \ expr' ->
+    returnSmpl (mkGenApp (mkCoerce coercion (simplTy env ty) expr') args)
+  where
+
+       -- Try cancellation; we do this "on the way up" because
+       -- I think that's where it'll bite best
+    mkCoerce (CoerceOut con1) ty1 (Coerce (CoerceIn  con2) ty2 body) | con1 == con2 = body
+    mkCoerce coercion ty  body = Coerce coercion ty body
 \end{code}
 
 
@@ -672,7 +680,7 @@ simplLam env binders body min_no_of_args
 simplBind :: SimplEnv
          -> InBinding
          -> (SimplEnv -> SmplM OutExpr)
-         -> OutUniType
+         -> OutType
          -> SmplM OutExpr
 \end{code}
 
@@ -703,11 +711,11 @@ becomes:
 
 ==>
       let join_body x' = foldr c n x'
-        in case y of
-        p1 -> let x* = build e1
-                in join_body x*
-        p2 -> let x* = build e2
-                in join_body x*
+       in case y of
+       p1 -> let x* = build e1
+               in join_body x*
+       p2 -> let x* = build e2
+               in join_body x*
 
 note that join_body is a let-no-escape.
 In this particular example join_body will later be inlined,
@@ -719,120 +727,129 @@ ToDo: check this is OK with andy
 \begin{code}
 -- Dead code is now discarded by the occurrence analyser,
 
-simplBind env (CoNonRec binder@(id,occ_info) rhs) body_c body_ty
-  |  inlineUnconditionally ok_to_dup occ_info
-  = body_c (extendIdEnvWithInlining env env binder rhs)
-
--- Try let-to-case
--- It's important to try let-to-case before floating. Consider
---
---     let a*::Int = case v of {p1->e1; p2->e2}
---     in b
---
--- (The * means that a is sure to be demanded.)
--- If we do case-floating first we get this:
---
---     let k = \a* -> b
---     in case v of 
---             p1-> let a*=e1 in k a
---             p2-> let a*=e2 in k a
---
--- Now watch what happens if we do let-to-case first:
---
---     case (case v of {p1->e1; p2->e2}) of
---       Int a# -> let a*=I# a# in b
--- ===>
---     let k = \a# -> let a*=I# a# in b
---     in case v of
---             p1 -> case e1 of I# a# -> k a#
---             p1 -> case e1 of I# a# -> k a#
---
--- The latter is clearly better.  (Remember the reboxing let-decl
--- for a is likely to go away, because after all b is strict in a.)
-
-  | will_be_demanded && 
-    try_let_to_case &&
-    type_ok_for_let_to_case rhs_ty &&
-    not (manifestlyWHNF rhs)
-       -- note: no "manifestlyBottom rhs" in there... (comment below)
-    = tick Let2Case                            `thenSmpl_`
-      mkIdentityAlts rhs_ty                    `thenSmpl` \ id_alts ->
-      simplCase env rhs id_alts (\env rhs -> done_float env rhs body_c) body_ty
-       {-
-       We do not do let to case for WHNFs, e.g.
-
-         let x = a:b in ...
-         =/=>
-         case a:b of x in ...
-
-         as this is less efficient.
-         but we don't mind doing let-to-case for "bottom", as that
-         will
-         allow us to remove more dead code, if anything:
-         let x = error in ...
-         ===>
-         case error  of x -> ...
-         ===>
-         error
+simplBind env (NonRec binder@(id,occ_info) rhs) body_c body_ty
+  = simpl_bind env rhs
+  where
+    -- Try let-to-case; see notes below about let-to-case
+    simpl_bind env rhs | will_be_demanded &&
+                        try_let_to_case &&
+                        type_ok_for_let_to_case rhs_ty &&
+                        not rhs_is_whnf        -- note: WHNF, but not bottom,  (comment below)
+      = tick Let2Case                          `thenSmpl_`
+        mkIdentityAlts rhs_ty                  `thenSmpl` \ id_alts ->
+        simplCase env rhs id_alts (\env rhs -> complete_bind env rhs) body_ty
+               -- NB: it's tidier to call complete_bind not simpl_bind, else
+               -- we nearly end up in a loop.  Consider:
+               --      let x = rhs in b
+               -- ==>  case rhs of (p,q) -> let x=(p,q) in b
+               -- This effectively what the above simplCase call does.
+               -- Now, the inner let is a let-to-case target again!  Actually, since
+               -- the RHS is in WHNF it won't happen, but it's a close thing!
+
+    -- Try let-from-let
+    simpl_bind env (Let bind rhs) | let_floating_ok
+      = tick LetFloatFromLet                    `thenSmpl_`
+       simplBind env (fix_up_demandedness will_be_demanded bind)
+                     (\env -> simpl_bind env rhs) body_ty
 
-         Notice that let to case occurs only if x is used strictly in
-         its body (obviously).
-       -}
+    -- Try case-from-let; this deals with a strict let of error too
+    simpl_bind env (Case scrut alts) | will_be_demanded || 
+                                      (float_primops && is_cheap_prim_app scrut)
+      = tick CaseFloatFromLet                          `thenSmpl_`
 
-  | will_be_demanded ||
-    always_float_let_from_let || 
-    floatExposesHNF float_lets float_primops ok_to_dup rhs
-  = try_float env rhs body_c
+       -- First, bind large let-body if necessary
+       if ok_to_dup || isSingleton (nonErrorRHSs alts)
+       then
+           simplCase env scrut alts (\env rhs -> simpl_bind env rhs) body_ty
+       else
+           bindLargeRhs env [binder] body_ty body_c    `thenSmpl` \ (extra_binding, new_body) ->
+           let
+               body_c' = \env -> simplExpr env new_body []
+               case_c  = \env rhs -> simplBind env (NonRec binder rhs) body_c' body_ty
+           in
+           simplCase env scrut alts case_c body_ty     `thenSmpl` \ case_expr ->
+           returnSmpl (Let extra_binding case_expr)
 
-  | otherwise
-  = done_float env rhs body_c
+    -- None of the above; simplify rhs and tidy up
+    simpl_bind env rhs = complete_bind env rhs
+    complete_bind env rhs
+      = simplRhsExpr env binder rhs            `thenSmpl` \ rhs' ->
+       cloneId env binder                      `thenSmpl` \ new_id ->
+       completeNonRec env binder new_id rhs'   `thenSmpl` \ (new_env, binds) ->
+        body_c new_env                         `thenSmpl` \ body' ->
+        returnSmpl (mkCoLetsAny binds body')
 
-  where
-    will_be_demanded = willBeDemanded (getIdDemandInfo id)
-    rhs_ty          = getIdUniType id
 
+       -- All this stuff is computed at the start of the simpl_bind loop
     float_lets               = switchIsSet env SimplFloatLetsExposingWHNF
     float_primops            = switchIsSet env SimplOkToFloatPrimOps
     ok_to_dup                = switchIsSet env SimplOkToDupCode
     always_float_let_from_let = switchIsSet env SimplAlwaysFloatLetsFromLets
     try_let_to_case           = switchIsSet env SimplLetToCase
+    no_float                 = switchIsSet env SimplNoLetFromStrictLet
 
-    -------------------------------------------
-    done_float env rhs body_c
-       = simplRhsExpr env binder rhs   `thenSmpl` \ rhs' ->
-         completeLet env binder rhs rhs' body_c body_ty
+    will_be_demanded = willBeDemanded (getIdDemandInfo id)
+    rhs_ty          = idType id
 
-    ---------------------------------------
-    try_float env (CoLet bind rhs) body_c
-      = tick LetFloatFromLet                    `thenSmpl_`
-        simplBind env (fix_up_demandedness will_be_demanded bind) 
-                     (\env -> try_float env rhs body_c) body_ty
+    rhs_is_whnf = case mkFormSummary rhs of
+                       VarForm -> True
+                       ValueForm -> True
+                       other -> False
 
-    try_float env (CoCase scrut alts) body_c
-      | will_be_demanded || (float_primops && is_cheap_prim_app scrut)
-      = tick CaseFloatFromLet                          `thenSmpl_`
+    let_floating_ok  = (will_be_demanded && not no_float) ||
+                      always_float_let_from_let ||
+                      floatExposesHNF float_lets float_primops ok_to_dup rhs
+\end{code}
 
-       -- First, bind large let-body if necessary
-       if no_need_to_bind_large_body then
-           simplCase env scrut alts (\env rhs -> try_float env rhs body_c) body_ty
-       else            
-           bindLargeRhs env [binder] body_ty body_c    `thenSmpl` \ (extra_binding, new_body) ->
-           let
-               body_c' = \env -> simplExpr env new_body []
-           in
-           simplCase env scrut alts 
-                     (\env rhs -> try_float env rhs body_c')
-                     body_ty                           `thenSmpl` \ case_expr ->
+Let to case
+~~~~~~~~~~~
+It's important to try let-to-case before floating. Consider
 
-           returnSmpl (CoLet extra_binding case_expr)
-      where
-       no_need_to_bind_large_body
-         = ok_to_dup || isSingleton (nonErrorRHSs alts)
+       let a*::Int = case v of {p1->e1; p2->e2}
+       in b
 
-    try_float env other_rhs body_c = done_float env other_rhs body_c
-\end{code}
+(The * means that a is sure to be demanded.)
+If we do case-floating first we get this:
+
+       let k = \a* -> b
+       in case v of
+               p1-> let a*=e1 in k a
+               p2-> let a*=e2 in k a
+
+Now watch what happens if we do let-to-case first:
+
+       case (case v of {p1->e1; p2->e2}) of
+         Int a# -> let a*=I# a# in b
+===>
+       let k = \a# -> let a*=I# a# in b
+       in case v of
+               p1 -> case e1 of I# a# -> k a#
+               p1 -> case e1 of I# a# -> k a#
+
+The latter is clearly better.  (Remember the reboxing let-decl for a
+is likely to go away, because after all b is strict in a.)
+
+We do not do let to case for WHNFs, e.g.
+
+         let x = a:b in ...
+         =/=>
+         case a:b of x in ...
+
+as this is less efficient.  but we don't mind doing let-to-case for
+"bottom", as that will allow us to remove more dead code, if anything:
+
+         let x = error in ...
+         ===>
+         case error  of x -> ...
+         ===>
+         error
+
+Notice that let to case occurs only if x is used strictly in its body
+(obviously).
 
-Letrec expressions 
+
+Letrec expressions
 ~~~~~~~~~~~~~~~~~~
 
 Simplify each RHS, float any let(recs) from the RHSs (if let-floating is
@@ -845,7 +862,7 @@ macro-expansion is:
        letrec
                f = ....g...
                g = ....f...
-       in 
+       in
        ....f...
 
 Here we would like the single call to g to be inlined.
@@ -901,12 +918,12 @@ group that are bound to constructors.  For example:
        /= a b    = unpack tuple a, unpack tuple b, call f
     in d.Eq
 
-here, by knowing about d.Eq in f's rhs, one could get rid of 
+here, by knowing about d.Eq in f's rhs, one could get rid of
 the case (and break out the recursion completely).
-[This occurred with more aggressive inlining threshold (4), 
+[This occurred with more aggressive inlining threshold (4),
 nofib/spectral/knights]
 
-How to do it?  
+How to do it?
        1: we simplify constructor rhss first.
        2: we record the "known constructors" in the environment
        3: we simplify the other rhss, with the knowledge about the constructors
@@ -914,44 +931,18 @@ How to do it?
 
 
 \begin{code}
-simplBind env (CoRec pairs) body_c body_ty
+simplBind env (Rec pairs) body_c body_ty
   =    -- Do floating, if necessary
-    (if float_lets || always_float_let_from_let
-     then 
-       mapSmpl float pairs     `thenSmpl` \ floated_pairs_s ->
-       returnSmpl (concat floated_pairs_s)
-     else
-       returnSmpl pairs
-    )                                  `thenSmpl` \ floated_pairs ->
-    let
-       binders = map fst floated_pairs
-    in
-    cloneIds env binders               `thenSmpl` \ ids' ->
     let
-       env_w_clones = extendIdEnvWithClones env binders ids'
-       triples      = ids' `zip` floated_pairs
-    in
-
-    simplRecursiveGroup env_w_clones triples   `thenSmpl` \ (binding, new_env) ->
+        floated_pairs | do_floating = float_pairs pairs
+                     | otherwise   = pairs
 
-    body_c new_env                             `thenSmpl` \ body' ->
-
-    returnSmpl (CoLet binding body')
+       ticks         | do_floating = length floated_pairs - length pairs
+                     | otherwise   = 0
 
-  where
-    ------------ Floating stuff -------------------
-
-    float_lets               = switchIsSet env SimplFloatLetsExposingWHNF
-    always_float_let_from_let = switchIsSet env SimplAlwaysFloatLetsFromLets
-
-    float (binder,rhs)
-      = let
-           pairs_s = float_pair (binder,rhs)
-       in
-       case pairs_s of
-         [_] -> returnSmpl pairs_s
-         more_than_one
-           -> tickN LetFloatFromLet (length pairs_s - 1) `thenSmpl_`
+       binders       = map fst floated_pairs
+    in
+    tickN LetFloatFromLet ticks                `thenSmpl_` 
                -- It's important to increment the tick counts if we
                -- do any floating.  A situation where this turns out
                -- to be important is this:
@@ -966,94 +957,74 @@ simplBind env (CoRec pairs) body_c body_ty
                -- mention x, in which case the y binding can be pulled
                -- out as an enclosing let(rec), which in turn gives
                -- the strictness analyser more chance.
-               returnSmpl pairs_s
+
+    cloneIds env binders                       `thenSmpl` \ ids' ->
+    let
+       env_w_clones = extendIdEnvWithClones env binders ids'
+    in
+    simplRecursiveGroup env_w_clones ids' floated_pairs        `thenSmpl` \ (binding, new_env) ->
+
+    body_c new_env                             `thenSmpl` \ body' ->
+
+    returnSmpl (Let binding body')
+
+  where
+    ------------ Floating stuff -------------------
+
+    float_lets               = switchIsSet env SimplFloatLetsExposingWHNF
+    always_float_let_from_let = switchIsSet env SimplAlwaysFloatLetsFromLets
+    do_floating              = float_lets || always_float_let_from_let
 
     float_pairs pairs = concat (map float_pair pairs)
 
     float_pair (binder, rhs)
        | always_float_let_from_let ||
          floatExposesHNF True False False rhs
-        = (binder,rhs') : pairs'
+       = (binder,rhs') : pairs'
 
        | otherwise
        = [(binder,rhs)]
-       where 
+       where
          (pairs', rhs') = do_float rhs
 
        -- Float just pulls out any top-level let(rec) bindings
     do_float :: InExpr -> ([(InBinder,InExpr)], InExpr)
-    do_float (CoLet (CoRec pairs) body)     = (float_pairs pairs    ++ pairs', body')
-                                           where
-                                             (pairs', body') = do_float body
-    do_float (CoLet (CoNonRec id rhs) body) = (float_pair (id,rhs) ++ pairs', body')
-                                           where
-                                             (pairs', body') = do_float body
+    do_float (Let (Rec pairs) body)     = (float_pairs pairs    ++ pairs', body')
+                                           where
+                                             (pairs', body') = do_float body
+    do_float (Let (NonRec id rhs) body) = (float_pair (id,rhs) ++ pairs', body')
+                                           where
+                                             (pairs', body') = do_float body
     do_float other                         = ([], other)
 
-simplRecursiveGroup env triples
-  =    -- Toss out all the dead pairs?  No, there shouldn't be any!
-       -- Dead code is discarded by the occurrence analyser
+simplRecursiveGroup env new_ids pairs 
+  =    -- Add unfoldings to the new_ids corresponding to their RHS
     let
-           -- Separate the live triples into "inline"able and
-           -- "ordinary" We're paranoid about duplication!
-       (inline_triples, ordinary_triples)
-         = partition is_inline_triple triples
-
-       is_inline_triple (_, ((_,occ_info),_))
-         = inlineUnconditionally False {-not ok_to_dup-} occ_info
-
-           -- Now add in the inline_pairs info (using "env_w_clones"),
-           -- so that we will save away suitably-clone-laden envs
-           -- inside the InlineIts...).
-
-           -- NOTE ALSO that we tie a knot here, because the
-           -- saved-away envs must also include these very inlinings
-           -- (they aren't stored anywhere else, and a late one might
-           -- be used in an early one).
-
-       env_w_inlinings = foldl add_inline env inline_triples
-
-       add_inline env (id', (binder,rhs))
-         = extendIdEnvWithInlining env env_w_inlinings binder rhs
-
-           -- Separate the remaining bindings into the ones which
-           -- need to be dealt with first (the "early" ones)
-           -- and the others (the "late" ones)
-       (early_triples, late_triples)
-         = partition is_early_triple ordinary_triples
-
-       is_early_triple (_, (_, CoCon _ _ _)) = True
-       is_early_triple (i, _               ) = idWantsToBeINLINEd i
+       binders        = map fst pairs
+       occs            = map snd binders
+       new_ids_w_pairs = zipEqual "simplRecGp" new_ids pairs
+       rhs_env         = foldl extendEnvForRecBinding 
+                              env new_ids_w_pairs
     in
-       -- Process the early bindings first
-    mapSmpl (do_one_binding env_w_inlinings) early_triples     `thenSmpl` \ early_triples' ->
 
-       -- Now further extend the environment to record our knowledge
-       -- about the form of the binders bound in the constructor bindings
-    let
-        env_w_early_info = foldr add_early_info env_w_inlinings early_triples'
-        add_early_info (binder, (id', rhs')) env = extendUnfoldEnvGivenRhs env binder id' rhs'
-    in
-       -- Now process the non-constructor bindings
-    mapSmpl (do_one_binding env_w_early_info) late_triples     `thenSmpl` \ late_triples' ->
+    mapSmpl (\(binder,rhs) -> simplRhsExpr rhs_env binder rhs) pairs   `thenSmpl` \ new_rhss ->
 
-       -- Phew! We're done
     let
-       binding = CoRec (map snd early_triples' ++ map snd late_triples')
-    in
-    returnSmpl (binding, env_w_early_info)
-  where
+       new_pairs       = zipEqual "simplRecGp" new_ids new_rhss
+       occs_w_new_pairs = zipEqual "simplRecGp" occs new_pairs
+       new_env         = foldl add_binding env occs_w_new_pairs
 
-    do_one_binding env (id', (binder,rhs)) 
-      = simplRhsExpr env binder rhs `thenSmpl` \ rhs' ->
-       returnSmpl (binder, (id', rhs'))
+       add_binding env (occ_info,(new_id,new_rhs)) 
+         = extendEnvGivenBinding env occ_info new_id new_rhs
+    in
+    returnSmpl (Rec new_pairs, new_env)
 \end{code}
 
 
 @completeLet@ looks at the simplified post-floating RHS of the
 let-expression, and decides what to do.  There's one interesting
 aspect to this, namely constructor reuse.  Consider
-@      
+@
        f = \x -> case x of
                    (y:ys) -> y:ys
                    []     -> ...
@@ -1068,7 +1039,7 @@ const.Int.max.wrk{-s2516-} =
          a.s3299 :: Int
          _N_ {-# U(P) #-}
          a.s3299 = I#! upk.s3297#
-       } in 
+       } in
          case (const.Int._tagCmp.wrk{-s2513-} upk.s3297# upk.s3298#) of {
            _LT -> I#! upk.s3298#
            _EQ -> a.s3299
@@ -1083,81 +1054,72 @@ only do the reverse (turn a constructor application back into a
 variable) when we find a let-expression:
 @
        let x = C a1 .. an
-       in 
-       ... (let y = C a1 .. an in ...) ... 
+       in
+       ... (let y = C a1 .. an in ...) ...
 @
 where it is always good to ditch the binding for y, and replace y by
 x.  That's just what completeLetBinding does.
 
-\begin{code}
-completeLet
-       :: SimplEnv
-       -> InBinder
-       -> InExpr               -- Original RHS
-       -> OutExpr              -- The simplified RHS
-       -> (SimplEnv -> SmplM OutExpr)          -- Body handler
-       -> OutUniType           -- Type of body
-       -> SmplM OutExpr
-
-completeLet env binder@(id,binder_info) old_rhs new_rhs body_c body_ty
 
-  -- See if RHS is an atom, or a reusable constructor
-  | maybeToBool maybe_atomic_rhs
-  = let
-       new_env = extendIdEnvWithAtom env binder rhs_atom
-    in
-    tick atom_tick_type                        `thenSmpl_`
-    body_c new_env
-
-  -- Maybe the rhs is an application of error, and sure to be demanded
-  | will_be_demanded && 
-    maybeToBool maybe_error_app
-  = tick CaseOfError                   `thenSmpl_`
-    returnSmpl retyped_error_app
-
-  -- The general case
-  | otherwise
-  = cloneId env binder                 `thenSmpl` \ id' ->
+\begin{code}
+       -- We want to ensure that all let-bound Coerces have 
+       -- atomic bodies, so they can freely be inlined.
+completeNonRec env binder new_id (Coerce coercion ty rhs)
+  | not (is_atomic rhs)
+  = newId (coreExprType rhs)                           `thenSmpl` \ inner_id ->
+    completeNonRec env 
+                  (inner_id, dangerousArgOcc) inner_id rhs `thenSmpl` \ (env1, binds1) ->
+       -- Dangerous occ because, like constructor args,
+       -- it can be duplicated easily
     let
-       env1    = extendIdEnvWithClone env binder id'
-       new_env = _scc_ "euegR2" (extendUnfoldEnvGivenRhs env1 binder id' new_rhs)
+       atomic_rhs = case lookupId env1 inner_id of
+                       LitArg l -> Lit l
+                       VarArg v -> Var v
     in
-    body_c new_env                     `thenSmpl` \ body' ->
-    returnSmpl (CoLet (CoNonRec id' new_rhs) body')
+    completeNonRec env1 binder new_id
+                  (Coerce coercion ty atomic_rhs)      `thenSmpl` \ (env2, binds2) ->
 
+    returnSmpl (env2, binds1 ++ binds2)
   where
-    will_be_demanded = willBeDemanded (getIdDemandInfo id)
-    try_to_reuse_constr   = switchIsSet env SimplReuseCon
-
-    Just (rhs_atom, atom_tick_type) = maybe_atomic_rhs
-
-    maybe_atomic_rhs :: Maybe (OutAtom, TickType)
-       -- If the RHS is atomic, we return Just (atom, tick type)
-       -- otherwise Nothing
-
-    maybe_atomic_rhs
-      = case new_rhs of
-         CoVar var -> Just (CoVarAtom var, AtomicRhs)
-
-         CoLit lit | not (isNoRepLit lit) 
-           -> Just (CoLitAtom lit, AtomicRhs)
-
-         CoCon con tys con_args
-           | try_to_reuse_constr 
-                  -- Look out for
-                  --   let v = C args
-                  --   in 
-                  --- ...(let w = C same-args in ...)...
-                  -- Then use v instead of w.   This may save
-                  -- re-constructing an existing constructor.
-            -> case lookForConstructor env con tys con_args of
-                 Nothing  -> Nothing
-                 Just var -> Just (CoVarAtom var, ConReused)
-
-         other -> Nothing
-
-    maybe_error_app        = maybeErrorApp new_rhs (Just body_ty)
-    Just retyped_error_app = maybe_error_app
+    is_atomic (Var v) = True
+    is_atomic (Lit l) = not (isNoRepLit l)
+    is_atomic other   = False
+       
+       -- Atomic right-hand sides.
+       -- We used to have a "tick AtomicRhs" in here, but it causes more trouble
+       -- than it's worth.  For a top-level binding a = b, where a is exported,
+       -- we can't drop the binding, so we get repeated AtomicRhs ticks
+completeNonRec env binder new_id rhs@(Var v)
+  = returnSmpl (extendIdEnvWithAtom env binder (VarArg v), [NonRec new_id rhs])
+
+completeNonRec env binder new_id rhs@(Lit lit)
+  | not (isNoRepLit lit)
+  = returnSmpl (extendIdEnvWithAtom env binder (LitArg lit), [NonRec new_id rhs])
+
+       -- Right hand sides that are constructors
+       --      let v = C args
+       --      in
+       --- ...(let w = C same-args in ...)...
+       -- Then use v instead of w.      This may save
+       -- re-constructing an existing constructor.
+completeNonRec env binder new_id rhs@(Con con con_args)
+  | switchIsSet env SimplReuseCon && 
+    maybeToBool maybe_existing_con &&
+    not (externallyVisibleId new_id)           -- Don't bother for exported things
+                                               -- because we won't be able to drop
+                                               -- its binding.
+  = tick ConReused             `thenSmpl_`
+    returnSmpl (extendIdEnvWithAtom env binder (VarArg it), [NonRec new_id rhs])
+  where
+    maybe_existing_con = lookForConstructor env con con_args
+    Just it           = maybe_existing_con
+
+       -- Default case
+completeNonRec env binder@(id,occ_info) new_id rhs
+ = returnSmpl (new_env, [NonRec new_id rhs])
+ where
+   env1    = extendIdEnvWithClone env binder new_id
+   new_env = extendEnvGivenBinding env1 occ_info new_id rhs
 \end{code}
 
 %************************************************************************
@@ -1167,23 +1129,13 @@ completeLet env binder@(id,binder_info) old_rhs new_rhs body_c body_ty
 %************************************************************************
 
 \begin{code}
-simplAtom :: SimplEnv -> InAtom -> OutAtom
-
-simplAtom env (CoLitAtom lit) = CoLitAtom lit
+simplArg :: SimplEnv -> InArg -> OutArg
 
-simplAtom env (CoVarAtom id)
-  | isLocallyDefined id
-  = case lookupId env id of
-       Just (ItsAnAtom atom) -> atom
-       Just (InlineIt _ _ _) -> pprPanic "simplAtom InLineIt:" (ppAbove (ppr PprDebug id) (pprSimplEnv env))
-       Nothing               -> CoVarAtom id   -- Must be an uncloned thing
-
-  | otherwise
-  =    -- Not locally defined, so no change
-    CoVarAtom id
+simplArg env (LitArg lit) = LitArg lit
+simplArg env (TyArg  ty)  = TyArg  (simplTy env ty)
+simplArg env (VarArg id)  = lookupId env id
 \end{code}
 
-
 %************************************************************************
 %*                                                                     *
 \subsection[Simplify-quickies]{Some local help functions}
@@ -1194,29 +1146,29 @@ simplAtom env (CoVarAtom id)
 \begin{code}
 -- fix_up_demandedness switches off the willBeDemanded Info field
 -- for bindings floated out of a non-demanded let
-fix_up_demandedness True {- Will be demanded -} bind 
+fix_up_demandedness True {- Will be demanded -} bind
    = bind      -- Simple; no change to demand info needed
-fix_up_demandedness False {- May not be demanded -} (CoNonRec binder rhs)
-   = CoNonRec (un_demandify binder) rhs
-fix_up_demandedness False {- May not be demanded -} (CoRec pairs)
-   = CoRec [(un_demandify binder, rhs) | (binder,rhs) <- pairs]
+fix_up_demandedness False {- May not be demanded -} (NonRec binder rhs)
+   = NonRec (un_demandify binder) rhs
+fix_up_demandedness False {- May not be demanded -} (Rec pairs)
+   = Rec [(un_demandify binder, rhs) | (binder,rhs) <- pairs]
 
 un_demandify (id, occ_info) = (id `addIdDemandInfo` noInfo, occ_info)
 
-is_cheap_prim_app (CoPrim op tys args) = primOpOkForSpeculation op
-is_cheap_prim_app other                       = False
+is_cheap_prim_app (Prim op _) = primOpOkForSpeculation op
+is_cheap_prim_app other              = False
 
-computeResultType :: SimplEnv -> InExpr -> [OutArg] -> OutUniType
+computeResultType :: SimplEnv -> InExpr -> [OutArg] -> OutType
 computeResultType env expr args
-  = do expr_ty' args
+  = go expr_ty' args
   where
-    expr_ty  = typeOfCoreExpr (unTagBinders expr)
+    expr_ty  = coreExprType (unTagBinders expr)
     expr_ty' = simplTy env expr_ty
 
-    do ty [] = ty
-    do ty (TypeArg ty_arg : args) = do (applyTy ty ty_arg) args
-    do ty (ValArg a       : args) = case maybeUnpackFunTy ty of
-                                     Just (_, res_ty) -> do res_ty args
-                                     Nothing          -> panic "computeResultType"
+    go ty [] = ty
+    go ty (TyArg ty_arg : args) = go (mkAppTy ty ty_arg) args
+    go ty (a:args) | isValArg a = case (getFunTy_maybe ty) of
+                                   Just (_, res_ty) -> go res_ty args
+                                   Nothing          -> panic "computeResultType"
 \end{code}