[project @ 1997-05-18 23:29:18 by sof]
[ghc-hetmet.git] / ghc / compiler / simplCore / SimplUtils.lhs
index e0ac4aa..a92ae3f 100644 (file)
@@ -1,5 +1,5 @@
 %
-% (c) The AQUA Project, Glasgow University, 1993-1995
+% (c) The AQUA Project, Glasgow University, 1993-1996
 %
 \section[SimplUtils]{The simplifier utilities}
 
@@ -9,47 +9,43 @@
 module SimplUtils (
 
        floatExposesHNF,
-       
-       mkCoTyLamTryingEta, mkCoLamTryingEta,
+
+       etaCoreExpr, mkRhsTyLam,
 
        etaExpandCount,
-       
+
        mkIdentityAlts,
 
        simplIdWantsToBeINLINEd,
 
-       type_ok_for_let_to_case
+       singleConstructorType, typeOkForCase
     ) where
 
-IMPORT_Trace           -- ToDo: rm (debugging)
-import Pretty
-
-import TaggedCore
-import PlainCore
-import SimplEnv
-import SimplMonad
+IMP_Ubiq(){-uitous-}
+IMPORT_DELOOPER(SmplLoop)              -- paranoia checking
 
 import BinderInfo
-
-import AbsPrel         ( primOpIsCheap, realWorldStateTy, buildId
-                         IF_ATTACK_PRAGMAS(COMMA realWorldTy)
-                         IF_ATTACK_PRAGMAS(COMMA tagOf_PrimOp)
-                         IF_ATTACK_PRAGMAS(COMMA pprPrimOp)
+import CmdLineOpts     ( opt_DoEtaReduction, SimplifierSwitch(..) )
+import CoreSyn
+import CoreUnfold      ( SimpleUnfolding, mkFormSummary, exprIsTrivial, FormSummary(..) )
+import Id              ( idType, isBottomingId, addInlinePragma, addIdDemandInfo,
+                         idWantsToBeINLINEd, dataConArgTys, SYN_IE(Id),
+                         getIdArity, GenId{-instance Eq-}
                        )
-import AbsUniType      ( extractTyVarsFromTy, getTyVarMaybe, isPrimType,
-                         splitTypeWithDictsAsArgs, getUniDataTyCon_maybe,
-                         applyTy, isFunType, TyVar, TyVarTemplate
-                         IF_ATTACK_PRAGMAS(COMMA cmpTyVar COMMA cmpClass)
-                       )
-import Id              ( getInstantiatedDataConSig, isDataCon, getIdUniType,
-                         getIdArity, isBottomingId, idWantsToBeINLINEd,
-                         DataCon(..), Id
+import IdInfo          ( ArityInfo(..), DemandInfo )
+import Maybes          ( maybeToBool )
+import PrelVals                ( augmentId, buildId )
+import PrimOp          ( primOpIsCheap )
+import SimplEnv
+import SimplMonad
+import Type            ( tyVarsOfType, mkForAllTys, mkTyVarTys, isPrimType, 
+                         maybeAppDataTyConExpandingDicts, SYN_IE(Type)
                        )
-import IdInfo
-import CmdLineOpts     ( SimplifierSwitch(..) )
-import Maybes          ( maybeToBool, Maybe(..) )
-import Outputable      -- isExported ...
-import Util
+import TysWiredIn      ( realWorldStateTy )
+import TyVar           ( elementOfTyVarSet,
+                         GenTyVar{-instance Eq-} )
+import Util            ( isIn, panic )
+
 \end{code}
 
 
@@ -64,25 +60,31 @@ floatExposesHNF
        :: Bool                 -- Float let(rec)s out of rhs
        -> Bool                 -- Float cheap primops out of rhs
        -> Bool                 -- OK to duplicate code
-       -> CoreExpr bdr Id
+       -> GenCoreExpr bdr Id tyvar uvar
        -> Bool
 
 floatExposesHNF float_lets float_primops ok_to_dup rhs
   = try rhs
   where
-    try (CoCase (CoPrim _ _ _) (CoPrimAlts alts deflt) )
+    try (Case (Prim _ _) (PrimAlts alts deflt) )
       | float_primops && (null alts || ok_to_dup)
       = or (try_deflt deflt : map try_alt alts)
 
-    try (CoLet bind body) | float_lets = try body
+    try (Let bind body) | float_lets = try body
 
     --    `build g'
     -- is like a HNF,
     -- because it *will* become one.
-    try (CoApp (CoTyApp (CoVar bld) _) _) | bld == buildId = True
+    -- likewise for `augment g h'
+    --
+    try (App (App (Var bld) _) _)        | bld == buildId   = True
+    try (App (App (App (Var aug) _) _) _) | aug == augmentId = True
 
-    try other = manifestlyWHNF other
-       {- but *not* necessarily "manifestlyBottom other"...
+    try other = case mkFormSummary other of
+                       VarForm   -> True
+                       ValueForm -> True
+                       other     -> False
+       {- but *not* necessarily "BottomForm"...
 
           We may want to float a let out of a let to expose WHNFs,
            but to do that to expose a "bottom" is a Bad Idea:
@@ -98,21 +100,119 @@ floatExposesHNF float_lets float_primops ok_to_dup rhs
            to allocate it eagerly as that's a waste.
        -}
 
-    try_alt (lit,rhs)               = try rhs
+    try_alt (lit,rhs) = try rhs
 
-    try_deflt CoNoDefault           = False
-    try_deflt (CoBindDefault _ rhs) = try rhs 
+    try_deflt NoDefault           = False
+    try_deflt (BindDefault _ rhs) = try rhs
 \end{code}
 
 
-Eta reduction on ordinary lambdas
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We have a go at doing
+Local tyvar-lifting
+~~~~~~~~~~~~~~~~~~~
+mkRhsTyLam tries this transformation, when the big lambda appears as
+the RHS of a let(rec) binding:
+
+       /\abc -> let(rec) x = e in b
+   ==>
+       let(rec) x' = /\abc -> let x = x' a b c in e
+       in 
+       /\abc -> let x = x' a b c in b
+
+This is good because it can turn things like:
+
+       let f = /\a -> letrec g = ... g ... in g
+into
+       letrec g' = /\a -> ... g' a ...
+       in
+       let f = /\ a -> f a
+
+which is better.  In effect, it means that big lambdas don't impede
+let-floating.
 
-       \ x y -> f x y  ===>  f
+This optimisation is CRUCIAL in eliminating the junk introduced by
+desugaring mutually recursive definitions.  Don't eliminate it lightly!
+
+So far as the implemtation is concerned:
+
+       Invariant: go F e = /\tvs -> F e
+       
+       Equalities:
+               go F (Let x=e in b)
+               = Let x' = /\tvs -> F e 
+                 in 
+                 go G b
+               where
+                   G = F . Let x = x' tvs
+       
+               go F (Letrec xi=ei in b)
+               = Letrec {xi' = /\tvs -> G ei} 
+                 in
+                 go G b
+               where
+                 G = F . Let {xi = xi' tvs}
+
+\begin{code}
+mkRhsTyLam [] body = returnSmpl body
+
+mkRhsTyLam tyvars body
+  = go (\x -> x) body
+  where
+    tyvar_tys = mkTyVarTys tyvars
+
+    go fn (Let bind@(NonRec var rhs) body) | exprIsTrivial rhs
+      = go (fn . Let bind) body
+
+    go fn (Let bind@(NonRec var rhs) body)
+      = mk_poly var                            `thenSmpl` \ (var', rhs') ->
+       go (fn . Let (mk_silly_bind var rhs')) body     `thenSmpl` \ body' ->
+       returnSmpl (Let (NonRec var' (mkTyLam tyvars (fn rhs))) body')
+
+    go fn (Let (Rec prs) body)
+       = mapAndUnzipSmpl mk_poly vars          `thenSmpl` \ (vars', rhss') ->
+        let
+           gn body = fn $ foldr Let body (zipWith mk_silly_bind vars rhss')
+        in
+        go gn body                             `thenSmpl` \ body' ->
+        returnSmpl (Let (Rec (vars' `zip` [mkTyLam tyvars (gn rhs) | rhs <- rhss])) body')
+       where
+        (vars,rhss) = unzip prs
+
+    go fn body = returnSmpl (mkTyLam tyvars (fn body))
+
+    mk_poly var
+      = newId (mkForAllTys tyvars (idType var))        `thenSmpl` \ poly_id ->
+       returnSmpl (poly_id, mkTyApp (Var poly_id) tyvar_tys)
+
+    mk_silly_bind var rhs = NonRec (addInlinePragma var) rhs
+               -- The addInlinePragma is really important!  If we don't say 
+               -- INLINE on these silly little bindings then look what happens!
+               -- Suppose we start with:
+               --
+               --      x = let g = /\a -> \x -> f x x
+               --          in 
+               --          /\ b -> let g* = g b in E
+               --
+               -- Then:        * the binding for g gets floated out
+               --              * but then it gets inlined into the rhs of g*
+               --              * then the binding for g* is floated out of the /\b
+               --              * so we're back to square one
+               -- The silly binding for g* must be INLINE, so that no inlining
+               -- will happen in its RHS.
+\end{code}
+
+Eta reduction
+~~~~~~~~~~~~~
+@etaCoreExpr@ trys an eta reduction at the top level of a Core Expr.
+
+e.g.   \ x y -> f x y  ===>  f
+
+It is used
+       a) Before constructing an Unfolding, to 
+          try to make the unfolding smaller;
+       b) In tidyCoreExpr, which is done just before converting to STG.
 
 But we only do this if it gets rid of a whole lambda, not part.
-The idea is that lambdas are often quite helpful: they indicate 
+The idea is that lambdas are often quite helpful: they indicate
 head normal forms, so we don't want to chuck them away lightly.
 But if they expose a simple variable then we definitely win.  Even
 if they expose a type application we win.  So we check for this special
@@ -125,41 +225,75 @@ It does arise:
 gives rise to a recursive function for the list comprehension, and
 f turns out to be just a single call to this recursive function.
 
+Doing eta on type lambdas is useful too:
+
+       /\a -> <expr> a    ===>     <expr>
+
+where <expr> doesn't mention a.
+This is sometimes quite useful, because we can get the sequence:
+
+       f ab d = let d1 = ...d... in
+                letrec f' b x = ...d...(f' b)... in
+                f' b
+specialise ==>
+
+       f.Int b = letrec f' b x = ...dInt...(f' b)... in
+                 f' b
+
+float ==>
+
+       f' b x = ...dInt...(f' b)...
+       f.Int b = f' b
+
+Now we really want to simplify to
+
+       f.Int = f'
+
+and then replace all the f's with f.Ints.
+
+N.B. We are careful not to partially eta-reduce a sequence of type
+applications since this breaks the specialiser:
+
+       /\ a -> f Char# a       =NO=> f Char#
+
 \begin{code}
-mkCoLamTryingEta :: [Id]               -- Args to the lambda
-              -> PlainCoreExpr         -- Lambda body
-              -> PlainCoreExpr
+etaCoreExpr :: CoreExpr -> CoreExpr
 
-mkCoLamTryingEta [] body = body
 
-mkCoLamTryingEta orig_ids body
-  = reduce_it (reverse orig_ids) body
+etaCoreExpr expr@(Lam bndr body)
+  | opt_DoEtaReduction
+  = case etaCoreExpr body of
+       App fun arg | eta_match bndr arg &&
+                     residual_ok fun
+                   -> fun                      -- Eta
+       other       -> expr                     -- Can't eliminate it, so do nothing at all
   where
-    bale_out = mkCoLam orig_ids body
-
-    reduce_it [] residual
-      | residual_ok residual = residual
-      | otherwise           = bale_out
-
-    reduce_it (id:ids) (CoApp fun (CoVarAtom arg))
-      | id == arg
-      && getIdUniType id /= realWorldStateTy
-         -- *never* eta-reduce away a PrimIO state token! (WDP 94/11)
-      = reduce_it ids fun
-
-    reduce_it ids other = bale_out
-
-    is_elem = isIn "mkCoLamTryingEta"
-
-    -----------
-    residual_ok :: PlainCoreExpr -> Bool       -- Checks for type application
-                                               -- and function not one of the 
-                                               -- bound vars
-    residual_ok (CoTyApp fun ty) = residual_ok fun
-    residual_ok (CoVar v)        = not (v `is_elem` orig_ids)  -- Fun mustn't be one of
-                                                               -- the bound ids
-    residual_ok other           = False
+    eta_match (ValBinder v) (VarArg v') = v == v'
+    eta_match (TyBinder tv) (TyArg  ty) = tv `elementOfTyVarSet` tyVarsOfType ty
+    eta_match bndr         arg         = False
+
+    residual_ok :: CoreExpr -> Bool    -- Checks for type application
+                                       -- and function not one of the
+                                       -- bound vars
+
+    residual_ok (Var v)
+       = not (eta_match bndr (VarArg v))
+    residual_ok (App fun arg)
+       | eta_match bndr arg = False
+       | otherwise          = residual_ok fun
+    residual_ok (Coerce coercion ty body)
+       | eta_match bndr (TyArg ty) = False
+       | otherwise                 = residual_ok body
+
+    residual_ok other       = False            -- Safe answer
+       -- This last clause may seem conservative, but consider:
+       --      primops, constructors, and literals, are impossible here
+       --      let and case are unlikely (the argument would have been floated inside)
+       --      SCCs we probably want to be conservative about (not sure, but it's safe to be)
+       
+etaCoreExpr expr = expr                -- The common case
 \end{code}
+       
 
 Eta expansion
 ~~~~~~~~~~~~~
@@ -168,61 +302,59 @@ such that
 
        E  ===>   (\x1::t1 x1::t2 ... xn::tn -> E x1 x2 ... xn)
 
-is a safe transformation.  In particular, the transformation should not
-cause work to be duplicated, unless it is ``cheap'' (see @manifestlyCheap@ below).
+is a safe transformation.  In particular, the transformation should
+not cause work to be duplicated, unless it is ``cheap'' (see
+@manifestlyCheap@ below).
 
-@etaExpandCount@ errs on the conservative side.  It is always safe to return 0.
+@etaExpandCount@ errs on the conservative side.  It is always safe to
+return 0.
 
 An application of @error@ is special, because it can absorb as many
-arguments as you care to give it.  For this special case we return 100,
-to represent "infinity", which is a bit of a hack.
+arguments as you care to give it.  For this special case we return
+100, to represent "infinity", which is a bit of a hack.
 
 \begin{code}
-etaExpandCount :: CoreExpr bdr Id
-              -> Int                   -- Number of extra args you can safely abstract
+etaExpandCount :: GenCoreExpr bdr Id tyvar uvar
+              -> Int   -- Number of extra args you can safely abstract
 
-etaExpandCount (CoLam ids body)
-  = length ids + etaExpandCount body
+etaExpandCount (Lam (ValBinder _) body)
+  = 1 + etaExpandCount body
 
-etaExpandCount (CoLet bind body) 
-  | all manifestlyCheap (rhssOfBind bind) 
+etaExpandCount (Let bind body)
+  | all manifestlyCheap (rhssOfBind bind)
   = etaExpandCount body
-   
-etaExpandCount (CoCase scrut alts)
-  | manifestlyCheap scrut 
-  = minimum [etaExpandCount rhs | rhs <- rhssOfAlts alts]
 
-etaExpandCount (CoApp fun _) = case etaExpandCount fun of
-                               0 -> 0
-                               n -> n-1        -- Knock off one
+etaExpandCount (Case scrut alts)
+  | manifestlyCheap scrut
+  = minimum [etaExpandCount rhs | rhs <- rhssOfAlts alts]
 
-etaExpandCount fun@(CoTyApp _ _) = eta_fun fun
-etaExpandCount fun@(CoVar _)     = eta_fun fun
+etaExpandCount fun@(Var _)     = eta_fun fun
+etaExpandCount (App fun arg)
+  | notValArg arg = eta_fun fun
+  | otherwise     = case etaExpandCount fun of
+                     0 -> 0
+                     n -> n-1  -- Knock off one
 
-etaExpandCount other = 0                       -- Give up
-       -- CoLit, CoCon, CoPrim, 
-       -- CoTyLam,
-       -- CoScc (pessimistic; ToDo),
-       -- CoLet with non-whnf rhs(s),
-       -- CoCase with non-whnf scrutinee
+etaExpandCount other = 0    -- Give up
+       -- Lit, Con, Prim,
+       -- non-val Lam,
+       -- Scc (pessimistic; ToDo),
+       -- Let with non-whnf rhs(s),
+       -- Case with non-whnf scrutinee
 
-eta_fun :: CoreExpr bdr Id     -- The function
-       -> Int                  -- How many args it can safely be applied to
+-----------------------------
+eta_fun :: GenCoreExpr bdr Id tv uv -- The function
+       -> Int                      -- How many args it can safely be applied to
 
-eta_fun (CoTyApp fun ty) = eta_fun fun
+eta_fun (App fun arg) | notValArg arg = eta_fun fun
 
-eta_fun expr@(CoVar v)
-  | isBottomingId v                    -- Bottoming ids have "infinite arity"
-  = 10000                              -- Blargh.  Infinite enough!
+eta_fun expr@(Var v)
+  | isBottomingId v            -- Bottoming ids have "infinite arity"
+  = 10000                      -- Blargh.  Infinite enough!
 
-eta_fun expr@(CoVar v)
-  | maybeToBool arity_maybe            -- We know the arity
-  = arity
-  where
-    arity_maybe = arityMaybe (getIdArity v)
-    arity      = case arity_maybe of { Just arity -> arity }
+eta_fun expr@(Var v) = idMinArity v
 
-eta_fun other = 0                      -- Give up
+eta_fun other = 0              -- Give up
 \end{code}
 
 @manifestlyCheap@ looks at a Core expression and returns \tr{True} if
@@ -231,7 +363,7 @@ By ``cheap'' we mean a computation we're willing to duplicate in order
 to bring a couple of lambdas together.  The main examples of things
 which aren't WHNF but are ``cheap'' are:
 
-  *    case e of 
+  *    case e of
          pi -> ei
 
        where e, and all the ei are cheap; and
@@ -246,149 +378,44 @@ which aren't WHNF but are ``cheap'' are:
        where op is a cheap primitive operator
 
 \begin{code}
-manifestlyCheap :: CoreExpr bndr Id -> Bool
+manifestlyCheap :: GenCoreExpr bndr Id tv uv -> Bool
 
-manifestlyCheap (CoVar _)       = True
-manifestlyCheap (CoLit _)       = True
-manifestlyCheap (CoCon _ _ _)   = True
-manifestlyCheap (CoLam _ _)     = True
-manifestlyCheap (CoTyLam _ e)   = manifestlyCheap e
-manifestlyCheap (CoSCC _ e)     = manifestlyCheap e
+manifestlyCheap (Var _)        = True
+manifestlyCheap (Lit _)        = True
+manifestlyCheap (Con _ _)      = True
+manifestlyCheap (SCC _ e)      = manifestlyCheap e
+manifestlyCheap (Coerce _ _ e) = manifestlyCheap e
+manifestlyCheap (Lam x e)      = if isValBinder x then True else manifestlyCheap e
+manifestlyCheap (Prim op _)    = primOpIsCheap op
 
-manifestlyCheap (CoPrim op _ _) = primOpIsCheap op
-
-manifestlyCheap (CoLet bind body)
+manifestlyCheap (Let bind body)
   = manifestlyCheap body && all manifestlyCheap (rhssOfBind bind)
 
-manifestlyCheap (CoCase scrut alts)
+manifestlyCheap (Case scrut alts)
   = manifestlyCheap scrut && all manifestlyCheap (rhssOfAlts alts)
 
 manifestlyCheap other_expr   -- look for manifest partial application
-  = case (collectArgs other_expr) of { (fun, args) ->
+  = case (collectArgs other_expr) of { (fun, _, _, vargs) ->
     case fun of
 
-      CoVar f | isBottomingId f -> True                -- Application of a function which
-                                               -- always gives bottom; we treat this as
-                                               -- a WHNF, because it certainly doesn't
-                                               -- need to be shared!
-
-      CoVar f -> let
-                   num_val_args = length [ a | (ValArg a) <- args ]
-                in 
-                num_val_args == 0 ||           -- Just a type application of
-                                               -- a variable (f t1 t2 t3)
-                                               -- counts as WHNF
-                case (arityMaybe (getIdArity f)) of
-                  Nothing     -> False
-                  Just arity  -> num_val_args < arity
+      Var f | isBottomingId f -> True  -- Application of a function which
+                                       -- always gives bottom; we treat this as
+                                       -- a WHNF, because it certainly doesn't
+                                       -- need to be shared!
+
+      Var f -> let
+                   num_val_args = length vargs
+              in
+              num_val_args == 0 ||     -- Just a type application of
+                                       -- a variable (f t1 t2 t3)
+                                       -- counts as WHNF
+              num_val_args < idMinArity f
 
       _ -> False
     }
 
-
--- ToDo: Move to CoreFuns
-
-rhssOfBind :: CoreBinding bndr bdee -> [CoreExpr bndr bdee]
-
-rhssOfBind (CoNonRec _ rhs) = [rhs]
-rhssOfBind (CoRec pairs)    = [rhs | (_,rhs) <- pairs]
-
-rhssOfAlts :: CoreCaseAlternatives bndr bdee -> [CoreExpr bndr bdee]
-
-rhssOfAlts (CoAlgAlts alts deflt)  = rhssOfDeflt deflt ++ 
-                                    [rhs | (_,_,rhs) <- alts]
-rhssOfAlts (CoPrimAlts alts deflt) = rhssOfDeflt deflt ++ 
-                                    [rhs | (_,rhs) <- alts]
-rhssOfDeflt CoNoDefault = []
-rhssOfDeflt (CoBindDefault _ rhs) = [rhs]
 \end{code}
 
-Eta reduction on type lambdas
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We have a go at doing 
-
-       /\a -> <expr> a    ===>     <expr>
-
-where <expr> doesn't mention a.
-This is sometimes quite useful, because we can get the sequence:
-
-       f ab d = let d1 = ...d... in
-                letrec f' b x = ...d...(f' b)... in
-                f' b
-specialise ==> 
-
-       f.Int b = letrec f' b x = ...dInt...(f' b)... in
-                 f' b
-
-float ==> 
-
-       f' b x = ...dInt...(f' b)...
-       f.Int b = f' b
-
-Now we really want to simplify to 
-
-       f.Int = f'
-
-and then replace all the f's with f.Ints.
-
-N.B. We are careful not to partially eta-reduce a sequence of type
-applications since this breaks the specialiser:
-
-       /\ a -> f Char# a       =NO=> f Char#
-
-\begin{code}
-mkCoTyLamTryingEta :: [TyVar] -> PlainCoreExpr -> PlainCoreExpr
-
-mkCoTyLamTryingEta tyvars tylam_body
-  = if
-       tyvars == tyvar_args && -- Same args in same order
-       check_fun fun           -- Function left is ok
-    then
-       -- Eta reduction worked
-       fun
-    else
-       -- The vastly common case
-       mkCoTyLam tyvars tylam_body
-  where
-    (tyvar_args, fun) = strip_tyvar_args [] tylam_body
-
-    strip_tyvar_args args_so_far tyapp@(CoTyApp fun ty)
-      = case getTyVarMaybe ty of
-         Just tyvar_arg -> strip_tyvar_args (tyvar_arg:args_so_far) fun
-         Nothing        -> (args_so_far, tyapp)
-
-    strip_tyvar_args args_so_far fun
-      = (args_so_far, fun)
-
-    check_fun (CoVar f) = True  -- Claim: tyvars not mentioned by type of f
-    check_fun other     = False
-
-{- OLD:
-mkCoTyLamTryingEta :: TyVar -> PlainCoreExpr -> PlainCoreExpr
-
-mkCoTyLamTryingEta tyvar body
-  = case body of 
-       CoTyApp fun ty ->
-           case getTyVarMaybe ty of
-               Just tyvar' | tyvar == tyvar' &&
-                             ok fun                    -> fun
-                       -- Ha!  So it's /\ a -> fun a, and fun is "ok"
-
-               other -> CoTyLam tyvar body
-       other -> CoTyLam tyvar body
-  where
-    is_elem = isIn "mkCoTyLamTryingEta"
-
-    ok :: PlainCoreExpr -> Bool        -- Returns True iff the expression doesn't
-                               -- mention tyvar
-
-    ok (CoVar v)       = True          -- Claim: tyvar not mentioned by type of v
-    ok (CoApp fun arg)  = ok fun       -- Claim: tyvar not mentioned by type of arg
-    ok (CoTyApp fun ty) = not (tyvar `is_elem` extractTyVarsFromTy ty) &&
-                         ok fun
-    ok other            = False
--}
-\end{code}
 
 Let to case
 ~~~~~~~~~~~
@@ -406,51 +433,98 @@ if there's many, or if it's a primitive type.
 
 \begin{code}
 mkIdentityAlts
-       :: UniType              -- type of RHS
+       :: Type                 -- type of RHS
+       -> DemandInfo           -- Appropriate demand info
        -> SmplM InAlts         -- result
 
-mkIdentityAlts rhs_ty
-  | isPrimType rhs_ty
-  = newId rhs_ty       `thenSmpl` \ binder ->
-    returnSmpl (CoPrimAlts [] (CoBindDefault (binder, bad_occ_info) (CoVar binder)))
-
-  | otherwise
-  = case getUniDataTyCon_maybe rhs_ty of
+mkIdentityAlts rhs_ty demand_info
+  = case (maybeAppDataTyConExpandingDicts rhs_ty) of
        Just (tycon, ty_args, [data_con]) ->  -- algebraic type suitable for unpacking
            let
-               (_,inst_con_arg_tys,_) = getInstantiatedDataConSig data_con ty_args
+               inst_con_arg_tys = dataConArgTys data_con ty_args
            in
            newIds inst_con_arg_tys     `thenSmpl` \ new_bindees ->
            let
-               new_binders = [ (b, bad_occ_info) | b <- new_bindees ] 
+               new_binders = [ (b, bad_occ_info) | b <- new_bindees ]
            in
            returnSmpl (
-             CoAlgAlts
-               [(data_con, new_binders, CoCon data_con ty_args (map CoVarAtom new_bindees))]
-               CoNoDefault
+             AlgAlts
+               [(data_con, new_binders, mkCon data_con [] ty_args (map VarArg new_bindees))]
+               NoDefault
            )
 
-       _ -> -- Multi-constructor or abstract algebraic type 
-            newId rhs_ty       `thenSmpl` \ binder ->
-            returnSmpl (CoAlgAlts [] (CoBindDefault (binder,bad_occ_info) (CoVar binder)))
+       _ -> panic "mkIdentityAlts"     -- Should never happen; only called for single-constructor types
   where
     bad_occ_info = ManyOcc 0   -- Non-committal!
+
+
+{-             SHOULD NEVER HAPPEN 
+  | isPrimType rhs_ty
+  = newId rhs_ty       `thenSmpl` \ binder ->
+    let
+       binder_w_info = binder `addIdDemandInfo` demand_info
+       -- It's occasionally really worth adding the right demand info.  Consider
+       --      let x = E in B
+       -- where x is sure to be demanded in B
+       -- We will transform to:
+       --      case E of x -> B
+       -- Now suppose that E simplifies to just y; we get
+       --      case y of x -> B
+       -- Because x is sure to be demanded, we can eliminate the case
+       -- even if pedantic-bottoms is on; but we need to have the right
+       -- demand-info on the default branch of the case.  That's what
+       -- we are doing here.
+    in
+    returnSmpl (PrimAlts [] (BindDefault (binder, bad_occ_info) (Var binder)))
+-}
 \end{code}
 
 \begin{code}
 simplIdWantsToBeINLINEd :: Id -> SimplEnv -> Bool
 
-simplIdWantsToBeINLINEd id env 
-  = if switchIsSet env IgnoreINLINEPragma 
+simplIdWantsToBeINLINEd id env
+  = {- We used to arrange that in the final simplification pass we'd switch
+       off all INLINE pragmas, so that we'd inline workers back into the
+       body of their wrapper if the wrapper hadn't itself been inlined by then.
+       This occurred especially for methods in dictionaries.
+
+       We no longer do this:
+               a) there's a good chance that the exported wrapper will get
+               inlined in some importing scope, in which case we don't 
+               want to lose the w/w idea.
+
+               b) The occurrence analyser must agree about what has an
+               INLINE pragma.  Not hard, but delicate.
+       
+               c) if the worker gets inlined we have to tell the wrapepr
+               that it's no longer a wrapper, else the interface file stuff
+               asks for a worker that no longer exists.
+                 
+    if switchIsSet env IgnoreINLINEPragma
     then False
-    else idWantsToBeINLINEd id
+    else 
+    -}
+
+    idWantsToBeINLINEd id
+
+idMinArity id = case getIdArity id of
+                       UnknownArity   -> 0
+                       ArityAtLeast n -> n
+                       ArityExactly n -> n
 
-type_ok_for_let_to_case :: UniType -> Bool
+singleConstructorType :: Type -> Bool
+singleConstructorType ty
+  = case (maybeAppDataTyConExpandingDicts ty) of
+      Just (tycon, ty_args, [con]) -> True
+      other                       -> False
 
-type_ok_for_let_to_case ty 
-  = case getUniDataTyCon_maybe ty of
+typeOkForCase :: Type -> Bool
+typeOkForCase ty
+  = case (maybeAppDataTyConExpandingDicts ty) of
       Nothing                                   -> False
       Just (tycon, ty_args, [])                 -> False
       Just (tycon, ty_args, non_null_data_cons) -> True
-      -- Null data cons => type is abstract
+      -- Null data cons => type is abstract, which code gen can't 
+      -- currently handle.  (ToDo: when return-in-heap is universal we
+      -- don't need to worry about this.)
 \end{code}