[project @ 2000-08-31 19:55:46 by simonpj]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CoreUtils.lhs
index 9b9b03c..5e9736b 100644 (file)
@@ -5,46 +5,66 @@
 
 \begin{code}
 module CoreUtils (
-       coreExprType, coreAltsType,
+       -- Construction
+       mkNote, mkInlineMe, mkSCC, mkCoerce,
+       bindNonRec, mkIfThenElse, mkAltExpr,
+        mkPiType,
 
+       -- Properties of expressions
+       exprType, coreAltsType, exprArity,
        exprIsBottom, exprIsDupable, exprIsTrivial, exprIsCheap, 
-       exprIsValue,
-       exprOkForSpeculation, exprIsBig, hashExpr,
-       exprArity, exprGenerousArity,
+       exprIsValue,exprOkForSpeculation, exprIsBig, 
+       exprIsConApp_maybe,
+       idAppIsBottom, idAppIsCheap,
+
+       -- Expr transformation
+       etaReduceExpr, exprEtaExpandArity,
+
+       -- Size
+       coreBindsSize,
+
+       -- Hashing
+       hashExpr,
+
+       -- Equality
        cheapEqExpr, eqExpr, applyTypeToArgs
     ) where
 
 #include "HsVersions.h"
 
 
-import {-# SOURCE #-} CoreUnfold       ( isEvaldUnfolding )
-
 import GlaExts         -- For `xori` 
 
 import CoreSyn
+import CoreFVs         ( exprFreeVars )
 import PprCore         ( pprCoreExpr )
-import Var             ( IdOrTyVar, isId, isTyVar )
+import Var             ( Var, isId, isTyVar )
 import VarSet
 import VarEnv
 import Name            ( isLocallyDefined, hashName )
-import Const           ( Con, isWHNFCon, conIsTrivial, conIsCheap, conIsDupable,
-                         conType, conOkForSpeculation, conStrictness, hashCon
-                       )
-import Id              ( Id, idType, setIdType, idUnique, idAppIsBottom,
-                         getIdArity, idName,
-                         getIdSpecialisation, setIdSpecialisation,
-                         getInlinePragma, setInlinePragma,
-                         getIdUnfolding, setIdUnfolding, idInfo
+import Literal         ( Literal, hashLiteral, literalType, litIsDupable )
+import DataCon         ( DataCon, dataConRepArity )
+import PrimOp          ( primOpOkForSpeculation, primOpIsCheap, 
+                         primOpIsDupable )
+import Id              ( Id, idType, idFlavour, idStrictness, idLBVarInfo, 
+                         mkWildId, idArity, idName, idUnfolding, idInfo, 
+                         isDataConId_maybe, isPrimOpId_maybe
                        )
-import IdInfo          ( arityLowerBound, InlinePragInfo(..), lbvarInfo, LBVarInfo(..) )
+import IdInfo          ( arityLowerBound, InlinePragInfo(..),
+                         LBVarInfo(..),  
+                         IdFlavour(..),
+                         megaSeqIdInfo )
+import Demand          ( appIsBottom )
 import Type            ( Type, mkFunTy, mkForAllTy,
                          splitFunTy_maybe, tyVarsOfType, tyVarsOfTypes,
                           isNotUsgTy, mkUsgTy, unUsgTy, UsageAnn(..),
-                         tidyTyVar, applyTys, isUnLiftedType
+                         applyTys, isUnLiftedType, seqType
                        )
-import Demand          ( isPrim, isLazy )
+import TysWiredIn      ( boolTy, stringTy, trueDataCon, falseDataCon )
+import CostCentre      ( CostCentre )
 import Unique          ( buildIdKey, augmentIdKey )
 import Util            ( zipWithEqual, mapAccumL )
+import Maybes          ( maybeToBool )
 import Outputable
 import TysPrim         ( alphaTy )     -- Debugging only
 \end{code}
@@ -57,31 +77,38 @@ import TysPrim              ( alphaTy )     -- Debugging only
 %************************************************************************
 
 \begin{code}
-coreExprType :: CoreExpr -> Type
-
-coreExprType (Var var)             = idType var
-coreExprType (Let _ body)          = coreExprType body
-coreExprType (Case _ _ alts)        = coreAltsType alts
-coreExprType (Note (Coerce ty _) e) = ty
-coreExprType (Note (TermUsg u) e)   = mkUsgTy u (unUsgTy (coreExprType e))
-coreExprType (Note other_note e)    = coreExprType e
-coreExprType e@(Con con args)       = applyTypeToArgs e (conType con) args
-
-coreExprType (Lam binder expr)
-  | isId binder    = (case (lbvarInfo . idInfo) binder of
-                       IsOneShotLambda -> mkUsgTy UsOnce
-                       otherwise       -> id) $
-                     idType binder `mkFunTy` coreExprType expr
-  | isTyVar binder = mkForAllTy binder (coreExprType expr)
-
-coreExprType e@(App _ _)
+exprType :: CoreExpr -> Type
+
+exprType (Var var)             = idType var
+exprType (Lit lit)             = literalType lit
+exprType (Let _ body)          = exprType body
+exprType (Case _ _ alts)        = coreAltsType alts
+exprType (Note (Coerce ty _) e) = ty  -- **! should take usage from e
+exprType (Note (TermUsg u) e)   = mkUsgTy u (unUsgTy (exprType e))
+exprType (Note other_note e)    = exprType e
+exprType (Lam binder expr)      = mkPiType binder (exprType expr)
+exprType e@(App _ _)
   = case collectArgs e of
-       (fun, args) -> applyTypeToArgs e (coreExprType fun) args
+       (fun, args) -> applyTypeToArgs e (exprType fun) args
 
-coreExprType other = pprTrace "coreExprType" (pprCoreExpr other) alphaTy
+exprType other = pprTrace "exprType" (pprCoreExpr other) alphaTy
 
 coreAltsType :: [CoreAlt] -> Type
-coreAltsType ((_,_,rhs) : _) = coreExprType rhs
+coreAltsType ((_,_,rhs) : _) = exprType rhs
+\end{code}
+
+@mkPiType@ makes a (->) type or a forall type, depending on whether
+it is given a type variable or a term variable.  We cleverly use the
+lbvarinfo field to figure out the right annotation for the arrove in
+case of a term variable.
+
+\begin{code}
+mkPiType :: Var -> Type -> Type                -- The more polymorphic version doesn't work...
+mkPiType v ty | isId v    = (case idLBVarInfo v of
+                               IsOneShotLambda -> mkUsgTy UsOnce
+                               otherwise       -> id) $
+                            mkFunTy (idType v) ty
+             | isTyVar v = mkForAllTy v ty
 \end{code}
 
 \begin{code}
@@ -91,7 +118,9 @@ applyTypeToArgs e op_ty [] = op_ty
 
 applyTypeToArgs e op_ty (Type ty : args)
   =    -- Accumulate type arguments so we can instantiate all at once
-    ASSERT2( all isNotUsgTy tys, ppr e <+> text "of" <+> ppr op_ty <+> text "to" <+> ppr (Type ty : args) <+> text "i.e." <+> ppr tys )
+    ASSERT2( all isNotUsgTy tys, 
+            ppr e <+> text "of" <+> ppr op_ty <+> text "to" <+> 
+            ppr (Type ty : args) <+> text "i.e." <+> ppr tys )
     applyTypeToArgs e (applyTys op_ty tys) rest_args
   where
     (tys, rest_args)        = go [ty] args
@@ -105,27 +134,126 @@ applyTypeToArgs e op_ty (other_arg : args)
 \end{code}
 
 
+
+%************************************************************************
+%*                                                                     *
+\subsection{Attaching notes}
+%*                                                                     *
+%************************************************************************
+
+mkNote removes redundant coercions, and SCCs where possible
+
+\begin{code}
+mkNote :: Note -> CoreExpr -> CoreExpr
+mkNote (Coerce to_ty from_ty) expr = mkCoerce to_ty from_ty expr
+mkNote (SCC cc)        expr               = mkSCC cc expr
+mkNote InlineMe expr              = mkInlineMe expr
+mkNote note     expr              = Note note expr
+
+-- Slide InlineCall in around the function
+--     No longer necessary I think (SLPJ Apr 99)
+-- mkNote InlineCall (App f a) = App (mkNote InlineCall f) a
+-- mkNote InlineCall (Var v)   = Note InlineCall (Var v)
+-- mkNote InlineCall expr      = expr
+\end{code}
+
+Drop trivial InlineMe's.  This is somewhat important, because if we have an unfolding
+that looks like        (Note InlineMe (Var v)), the InlineMe doesn't go away because it may
+not be *applied* to anything.
+
+\begin{code}
+mkInlineMe e | exprIsTrivial e = e
+            | otherwise       = Note InlineMe e
+\end{code}
+
+
+
+\begin{code}
+mkCoerce :: Type -> Type -> CoreExpr -> CoreExpr
+
+mkCoerce to_ty from_ty (Note (Coerce to_ty2 from_ty2) expr)
+  = ASSERT( from_ty == to_ty2 )
+    mkCoerce to_ty from_ty2 expr
+
+mkCoerce to_ty from_ty expr
+  | to_ty == from_ty = expr
+  | otherwise       = ASSERT( from_ty == exprType expr )
+                      Note (Coerce to_ty from_ty) expr
+\end{code}
+
+\begin{code}
+mkSCC :: CostCentre -> Expr b -> Expr b
+       -- Note: Nested SCC's *are* preserved for the benefit of
+       --       cost centre stack profiling (Durham)
+
+mkSCC cc (Lit lit) = Lit lit
+mkSCC cc (Lam x e) = Lam x (mkSCC cc e)        -- Move _scc_ inside lambda
+mkSCC cc expr     = Note (SCC cc) expr
+\end{code}
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Other expression construction}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+bindNonRec :: Id -> CoreExpr -> CoreExpr -> CoreExpr
+-- (bindNonRec x r b) produces either
+--     let x = r in b
+-- or
+--     case r of x { _DEFAULT_ -> b }
+--
+-- depending on whether x is unlifted or not
+-- It's used by the desugarer to avoid building bindings
+-- that give Core Lint a heart attack.  Actually the simplifier
+-- deals with them perfectly well.
+bindNonRec bndr rhs body 
+  | isUnLiftedType (idType bndr) = Case rhs bndr [(DEFAULT,[],body)]
+  | otherwise                   = Let (NonRec bndr rhs) body
+\end{code}
+
+\begin{code}
+mkAltExpr :: AltCon -> [CoreBndr] -> [Type] -> CoreExpr
+       -- This guy constructs the value that the scrutinee must have
+       -- when you are in one particular branch of a case
+mkAltExpr (DataAlt con) args inst_tys
+  = mkConApp con (map Type inst_tys ++ map varToCoreExpr args)
+mkAltExpr (LitAlt lit) [] []
+  = Lit lit
+
+mkIfThenElse :: CoreExpr -> CoreExpr -> CoreExpr -> CoreExpr
+mkIfThenElse guard then_expr else_expr
+  = Case guard (mkWildId boolTy) 
+        [ (DataAlt trueDataCon,  [], then_expr),
+          (DataAlt falseDataCon, [], else_expr) ]
+\end{code}
+
 %************************************************************************
 %*                                                                     *
 \subsection{Figuring out things about expressions}
 %*                                                                     *
 %************************************************************************
 
-@exprIsTrivial@        is true of expressions we are unconditionally 
-               happy to duplicate; simple variables and constants,
-               and type applications.
+@exprIsTrivial@ is true of expressions we are unconditionally happy to
+               duplicate; simple variables and constants, and type
+               applications.  Note that primop Ids aren't considered
+               trivial unless 
 
 @exprIsBottom@ is true of expressions that are guaranteed to diverge
 
 
 \begin{code}
-exprIsTrivial (Type _)      = True
-exprIsTrivial (Var v)       = True
-exprIsTrivial (App e arg)    = isTypeArg arg && exprIsTrivial e
-exprIsTrivial (Note _ e)     = exprIsTrivial e
-exprIsTrivial (Con con args) = conIsTrivial con && all isTypeArg args
-exprIsTrivial (Lam b body)   | isTyVar b = exprIsTrivial body
-exprIsTrivial other         = False
+exprIsTrivial (Var v)
+  | Just op <- isPrimOpId_maybe v      = primOpIsDupable op
+  | otherwise                          = True
+exprIsTrivial (Type _)                = True
+exprIsTrivial (Lit lit)               = True
+exprIsTrivial (App e arg)             = isTypeArg arg && exprIsTrivial e
+exprIsTrivial (Note _ e)              = exprIsTrivial e
+exprIsTrivial (Lam b body) | isTyVar b = exprIsTrivial body
+exprIsTrivial other                   = False
 \end{code}
 
 
@@ -142,14 +270,17 @@ exprIsTrivial other            = False
 
 \begin{code}
 exprIsDupable (Type _)      = True
-exprIsDupable (Con con args) = conIsDupable con && 
-                              all exprIsDupable args &&
-                              valArgCount args <= dupAppSize
-
+exprIsDupable (Var v)       = True
+exprIsDupable (Lit lit)      = litIsDupable lit
 exprIsDupable (Note _ e)     = exprIsDupable e
-exprIsDupable expr          = case collectArgs expr of  
-                                 (Var f, args) ->  valArgCount args <= dupAppSize
-                                 other         ->  False
+exprIsDupable expr          
+  = go expr 0
+  where
+    go (Var v)   n_args = True
+    go (App f a) n_args =  n_args < dupAppSize
+                       && exprIsDupable a
+                       && go f (n_args+1)
+    go other n_args    = False
 
 dupAppSize :: Int
 dupAppSize = 4         -- Size of application we are prepared to duplicate
@@ -188,34 +319,50 @@ because sharing will make sure it is only evaluated once.
 
 \begin{code}
 exprIsCheap :: CoreExpr -> Bool
-exprIsCheap (Type _)           = True
-exprIsCheap (Var _)            = True
-exprIsCheap (Con con args)     = conIsCheap con && all exprIsCheap args
-exprIsCheap (Note _ e)         = exprIsCheap e
-exprIsCheap (Lam x e)          = if isId x then True else exprIsCheap e
-exprIsCheap other_expr   -- look for manifest partial application
-  = case collectArgs other_expr of
-       (f, args) -> isPap f (valArgCount args) && all exprIsCheap args
-\end{code}
-
-\begin{code}
-isPap :: CoreExpr              -- Function
-      -> Int                   -- Number of value args
-      -> Bool
-isPap (Var f) n_val_args 
-  =    idAppIsBottom f n_val_args 
-                               -- Application of a function which
-                               -- always gives bottom; we treat this as
-                               -- a WHNF, because it certainly doesn't
-                               -- need to be shared!
-
-    || n_val_args == 0                 -- Just a type application of
+exprIsCheap (Lit lit)            = True
+exprIsCheap (Type _)             = True
+exprIsCheap (Var _)              = True
+exprIsCheap (Note _ e)           = exprIsCheap e
+exprIsCheap (Lam x e)            = if isId x then True else exprIsCheap e
+exprIsCheap (Case (Var v) _ alts) = and [exprIsCheap rhs | (_,_,rhs) <- alts]
+       -- Experimentally, treat (case x of ...) as cheap
+       -- This improves arities of overloaded functions where
+       -- there is only dictionary selection (no construction) involved
+exprIsCheap other_expr 
+  = go other_expr 0 True
+  where
+    go (Var f) n_args args_cheap 
+       = (idAppIsCheap f n_args && args_cheap)
+                       -- A constructor, cheap primop, or partial application
+
+         || idAppIsBottom f n_args 
+                       -- Application of a function which
+                       -- always gives bottom; we treat this as
+                       -- a WHNF, because it certainly doesn't
+                       -- need to be shared!
+       
+    go (App f a) n_args args_cheap 
+       | isTypeArg a = go f n_args       args_cheap
+       | otherwise   = go f (n_args + 1) (exprIsCheap a && args_cheap)
+
+    go other   n_args args_cheap = False
+
+idAppIsCheap :: Id -> Int -> Bool
+idAppIsCheap id n_val_args 
+  | n_val_args == 0 = True     -- Just a type application of
                                -- a variable (f t1 t2 t3)
                                -- counts as WHNF
-
-    || n_val_args < arityLowerBound (getIdArity f)
-               
-isPap fun n_val_args = False
+  | otherwise = case idFlavour id of
+                 DataConId _   -> True                 
+                 RecordSelId _ -> True                 -- I'm experimenting with making record selection
+                                                       -- look cheap, so we will substitute it inside a
+                                                       -- lambda.  Particularly for dictionary field selection
+
+                 PrimOpId op   -> primOpIsCheap op     -- In principle we should worry about primops
+                                                       -- that return a type variable, since the result
+                                                       -- might be applied to something, but I'm not going
+                                                       -- to bother to check the number of args
+                 other       -> n_val_args < idArity id
 \end{code}
 
 exprOkForSpeculation returns True of an expression that it is
@@ -229,7 +376,8 @@ It returns True iff
 
        the expression guarantees to terminate, 
        soon, 
-       without raising an exceptoin
+       without raising an exception,
+       without causing a side effect (e.g. writing a mutable variable)
 
 E.G.
        let x = case y# +# 1# of { r# -> I# r# }
@@ -245,17 +393,29 @@ side effects, and can't diverge or raise an exception.
 
 \begin{code}
 exprOkForSpeculation :: CoreExpr -> Bool
-exprOkForSpeculation (Var v)             = isUnLiftedType (idType v)
-exprOkForSpeculation (Note _ e)          = exprOkForSpeculation e
-
-exprOkForSpeculation (Con con args)
-  = conOkForSpeculation con &&
-    and (zipWith ok (filter isValArg args) (fst (conStrictness con)))
+exprOkForSpeculation (Lit _)    = True
+exprOkForSpeculation (Var v)    = isUnLiftedType (idType v)
+exprOkForSpeculation (Note _ e) = exprOkForSpeculation e
+exprOkForSpeculation other_expr
+  = go other_expr 0 True
   where
-    ok arg demand | isLazy demand = True
-                 | otherwise     = exprOkForSpeculation arg
-
-exprOkForSpeculation other = False     -- Conservative
+    go (Var f) n_args args_ok 
+      = case idFlavour f of
+         DataConId _ -> True   -- The strictness of the constructor has already
+                               -- been expressed by its "wrapper", so we don't need
+                               -- to take the arguments into account
+
+         PrimOpId op -> primOpOkForSpeculation op && args_ok
+                               -- A bit conservative: we don't really need
+                               -- to care about lazy arguments, but this is easy
+
+         other -> False
+       
+    go (App f a) n_args args_ok 
+       | isTypeArg a = go f n_args       args_ok
+       | otherwise   = go f (n_args + 1) (exprOkForSpeculation a && args_ok)
+
+    go other n_args args_ok = False
 \end{code}
 
 
@@ -269,8 +429,11 @@ exprIsBottom e = go 0 e
                 go n (Case e _ _) = go 0 e     -- Just check the scrut
                 go n (App e _)    = go (n+1) e
                 go n (Var v)      = idAppIsBottom v n
-                go n (Con _ _)    = False
+                go n (Lit _)      = False
                 go n (Lam _ _)    = False
+
+idAppIsBottom :: Id -> Int -> Bool
+idAppIsBottom id n_val_args = appIsBottom (idStrictness id) n_val_args
 \end{code}
 
 @exprIsValue@ returns true for expressions that are certainly *already* 
@@ -285,30 +448,117 @@ So, it does *not* treat variables as evaluated, unless they say they are
 exprIsValue :: CoreExpr -> Bool                -- True => Value-lambda, constructor, PAP
 exprIsValue (Type ty)    = True        -- Types are honorary Values; we don't mind
                                        -- copying them
-exprIsValue (Var v)              = isEvaldUnfolding (getIdUnfolding v)
+exprIsValue (Lit l)      = True
 exprIsValue (Lam b e)            = isId b || exprIsValue e
 exprIsValue (Note _ e)           = exprIsValue e
-exprIsValue (Let _ e)     = False
-exprIsValue (Case _ _ _)  = False
-exprIsValue (Con con _)   = isWHNFCon con 
-exprIsValue e@(App _ _)   = case collectArgs e of  
-                                 (Var v, args) -> fun_arity > valArgCount args
-                                               where
-                                                  fun_arity  = arityLowerBound (getIdArity v)
-                                 _             -> False
+exprIsValue other_expr
+  = go other_expr 0
+  where
+    go (Var f) n_args = idAppIsValue f n_args
+       
+    go (App f a) n_args
+       | isTypeArg a = go f n_args
+       | otherwise   = go f (n_args + 1) 
+
+    go (Note _ f) n_args = go f n_args
+
+    go other n_args = False
+
+idAppIsValue :: Id -> Int -> Bool
+idAppIsValue id n_val_args 
+  = case idFlavour id of
+       DataConId _ -> True
+       PrimOpId _  -> n_val_args < idArity id
+       other | n_val_args == 0 -> isEvaldUnfolding (idUnfolding id)
+             | otherwise       -> n_val_args < idArity id
+       -- A worry: what if an Id's unfolding is just itself: 
+       -- then we could get an infinite loop...
 \end{code}
 
 \begin{code}
 exprArity :: CoreExpr -> Int   -- How many value lambdas are at the top
 exprArity (Lam b e)     | isTyVar b    = exprArity e
                        | otherwise     = 1 + exprArity e
+
 exprArity (Note note e) | ok_note note = exprArity e
-exprArity other                                = 0
+                       where
+                         ok_note (Coerce _ _) = True
+                               -- We *do* look through coerces when getting arities.
+                               -- Reason: arities are to do with *representation* and
+                               -- work duplication. 
+                         ok_note InlineMe     = True
+                         ok_note InlineCall   = True
+                         ok_note other        = False
+                               -- SCC and TermUsg might be over-conservative?
+
+exprArity other        = 0
 \end{code}
 
+\begin{code}
+exprIsConApp_maybe :: CoreExpr -> Maybe (DataCon, [CoreExpr])
+exprIsConApp_maybe expr
+  = analyse (collectArgs expr)
+  where
+    analyse (Var fun, args)
+       | maybeToBool maybe_con_app = maybe_con_app
+       where
+         maybe_con_app = case isDataConId_maybe fun of
+                               Just con | length args >= dataConRepArity con 
+                                       -- Might be > because the arity excludes type args
+                                        -> Just (con, args)
+                               other    -> Nothing
+
+    analyse (Var fun, [])
+       = case maybeUnfoldingTemplate (idUnfolding fun) of
+               Nothing  -> Nothing
+               Just unf -> exprIsConApp_maybe unf
+
+    analyse other = Nothing
+\end{code} 
+
+
+%************************************************************************
+%*                                                                     *
+\subsection{Eta reduction and expansion}
+%*                                                                     *
+%************************************************************************
+
+@etaReduceExpr@ trys an eta reduction at the top level of a Core Expr.
+
+e.g.   \ x y -> f x y  ===>  f
+
+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
+head normal forms, so we don't want to chuck them away lightly.
 
 \begin{code}
-exprGenerousArity :: CoreExpr -> Int   -- The number of args the thing can be applied to
+etaReduceExpr :: CoreExpr -> CoreExpr
+               -- ToDo: we should really check that we don't turn a non-bottom
+               -- lambda into a bottom variable.  Sigh
+
+etaReduceExpr expr@(Lam bndr body)
+  = check (reverse binders) body
+  where
+    (binders, body) = collectBinders expr
+
+    check [] body
+       | not (any (`elemVarSet` body_fvs) binders)
+       = body                  -- Success!
+       where
+         body_fvs = exprFreeVars body
+
+    check (b : bs) (App fun arg)
+       |  (varToCoreExpr b `cheapEqExpr` arg)
+       = check bs fun
+
+    check _ _ = expr   -- Bale out
+
+etaReduceExpr expr = expr              -- The common case
+\end{code}
+       
+
+\begin{code}
+exprEtaExpandArity :: CoreExpr -> Int  -- The number of args the thing can be applied to
                                        -- without doing much work
 -- This is used when eta expanding
 --     e  ==>  \xy -> e x y
@@ -319,17 +569,34 @@ exprGenerousArity :: CoreExpr -> Int      -- The number of args the thing can be app
 -- We are prepared to evaluate x each time round the loop in order to get that
 -- Hence "generous" arity
 
-exprGenerousArity (Var v)              = arityLowerBound (getIdArity v)
-exprGenerousArity (Note note e)        
-  | ok_note note                       = exprGenerousArity e
-exprGenerousArity (Lam x e) 
-  | isId x                             = 1 + exprGenerousArity e
-  | otherwise                          = exprGenerousArity e
-exprGenerousArity (Let bind body)      
-  | all exprIsCheap (rhssOfBind bind)  = exprGenerousArity body
-exprGenerousArity (Case scrut _ alts)
-  | exprIsCheap scrut                  = min_zero [exprGenerousArity rhs | (_,_,rhs) <- alts]
-exprGenerousArity other                = 0     -- Could do better for applications
+exprEtaExpandArity e
+  = go e `max` 0       -- Never go -ve!
+  where
+    go (Var v)                                 = idArity v
+    go (App f (Type _))                        = go f
+    go (App f a)  | exprIsCheap a      = go f - 1
+    go (Lam x e)  | isId x             = go e + 1
+                 | otherwise           = go e
+    go (Note n e) | ok_note n          = go e
+    go (Case scrut _ alts)
+      | exprIsCheap scrut              = min_zero [go rhs | (_,_,rhs) <- alts]
+    go (Let b e)       
+      | all exprIsCheap (rhssOfBind b) = go e
+    
+    go other                           = 0
+    
+    ok_note (Coerce _ _) = True
+    ok_note InlineCall   = True
+    ok_note other        = False
+           -- Notice that we do not look through __inline_me__
+           -- This one is a bit more surprising, but consider
+           --  f = _inline_me (\x -> e)
+           -- We DO NOT want to eta expand this to
+           --  f = \x -> (_inline_me (\x -> e)) x
+           -- because the _inline_me gets dropped now it is applied, 
+           -- giving just
+           --  f = \x -> e
+           -- A Bad Idea
 
 min_zero :: [Int] -> Int       -- Find the minimum, but zero is the smallest
 min_zero (x:xs) = go x xs
@@ -339,24 +606,6 @@ min_zero (x:xs) = go x xs
                  go min (x:xs) | x < min   = go x xs
                                | otherwise = go min xs 
 
-ok_note (SCC _)             = False    -- (Over?) conservative
-ok_note (TermUsg _)  = False   -- Doesn't matter much
-
-ok_note (Coerce _ _) = True
-       -- We *do* look through coerces when getting arities.
-       -- Reason: arities are to do with *representation* and
-       -- work duplication. 
-
-ok_note InlineCall   = True
-ok_note InlineMe     = False
-       -- This one is a bit more surprising, but consider
-       --      f = _inline_me (\x -> e)
-       -- We DO NOT want to eta expand this to
-       --      f = \x -> (_inline_me (\x -> e)) x
-       -- because the _inline_me gets dropped now it is applied, 
-       -- giving just
-       --      f = \x -> e
-       -- A Bad Idea
 \end{code}
 
 
@@ -373,24 +622,21 @@ ok_note InlineMe     = False
 \begin{code}
 cheapEqExpr :: Expr b -> Expr b -> Bool
 
-cheapEqExpr (Var v1) (Var v2) = v1==v2
-cheapEqExpr (Con con1 args1) (Con con2 args2)
-  = con1 == con2 && 
-    and (zipWithEqual "cheapEqExpr" cheapEqExpr args1 args2)
+cheapEqExpr (Var v1)   (Var v2)   = v1==v2
+cheapEqExpr (Lit lit1) (Lit lit2) = lit1 == lit2
+cheapEqExpr (Type t1)  (Type t2)  = t1 == t2
 
 cheapEqExpr (App f1 a1) (App f2 a2)
   = f1 `cheapEqExpr` f2 && a1 `cheapEqExpr` a2
 
-cheapEqExpr (Type t1) (Type t2) = t1 == t2
-
 cheapEqExpr _ _ = False
 
 exprIsBig :: Expr b -> Bool
 -- Returns True of expressions that are too big to be compared by cheapEqExpr
+exprIsBig (Lit _)      = False
 exprIsBig (Var v)      = False
 exprIsBig (Type t)     = False
 exprIsBig (App f a)    = exprIsBig f || exprIsBig a
-exprIsBig (Con _ args) = any exprIsBig args
 exprIsBig other               = True
 \end{code}
 
@@ -408,7 +654,7 @@ eqExpr e1 e2
                                  Just v1' -> v1' == v2
                                  Nothing  -> v1  == v2
 
-    eq env (Con c1 es1) (Con c2 es2) = c1 == c2 && eq_list env es1 es2
+    eq env (Lit lit1)   (Lit lit2)   = lit1 == lit2
     eq env (App f1 a1)  (App f2 a2)  = eq env f1 f2 && eq env a1 a2
     eq env (Lam v1 e1)  (Lam v2 e2)  = eq (extendVarEnv env v1 v2) e1 e2
     eq env (Let (NonRec v1 r1) e1)
@@ -439,11 +685,59 @@ eqExpr e1 e2
                                         eq (extendVarEnvList env (vs1 `zip` vs2)) r1 r2
 
     eq_note env (SCC cc1)      (SCC cc2)      = cc1 == cc2
-    eq_note env (Coerce f1 t1) (Coerce f2 t2) = f1==f2 && t1==t2
+    eq_note env (Coerce t1 f1) (Coerce t2 f2) = t1==t2 && f1==f2
     eq_note env InlineCall     InlineCall     = True
     eq_note env other1        other2         = False
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+\subsection{The size of an expression}
+%*                                                                     *
+%************************************************************************
+
+\begin{code}
+coreBindsSize :: [CoreBind] -> Int
+coreBindsSize bs = foldr ((+) . bindSize) 0 bs
+
+exprSize :: CoreExpr -> Int
+       -- A measure of the size of the expressions
+       -- It also forces the expression pretty drastically as a side effect
+exprSize (Var v)       = varSize v 
+exprSize (Lit lit)     = lit `seq` 1
+exprSize (App f a)     = exprSize f + exprSize a
+exprSize (Lam b e)     = varSize b + exprSize e
+exprSize (Let b e)     = bindSize b + exprSize e
+exprSize (Case e b as) = exprSize e + varSize b + foldr ((+) . altSize) 0 as
+exprSize (Note n e)    = noteSize n + exprSize e
+exprSize (Type t)      = seqType t `seq` 1
+
+noteSize (SCC cc)       = cc `seq` 1
+noteSize (Coerce t1 t2) = seqType t1 `seq` seqType t2 `seq` 1
+noteSize InlineCall     = 1
+noteSize InlineMe       = 1
+noteSize (TermUsg usg)  = usg `seq` 1
+
+exprsSize = foldr ((+) . exprSize) 0 
+
+varSize :: Var -> Int
+varSize b  | isTyVar b = 1
+          | otherwise = seqType (idType b)             `seq`
+                        megaSeqIdInfo (idInfo b)       `seq`
+                        1
+
+varsSize = foldr ((+) . varSize) 0
+
+bindSize (NonRec b e) = varSize b + exprSize e
+bindSize (Rec prs)    = foldr ((+) . pairSize) 0 prs
+
+pairSize (b,e) = varSize b + exprSize e
+
+altSize (c,bs,e) = c `seq` varsSize bs + exprSize e
+\end{code}
+
+
 %************************************************************************
 %*                                                                     *
 \subsection{Hashing}
@@ -452,29 +746,27 @@ eqExpr e1 e2
 
 \begin{code}
 hashExpr :: CoreExpr -> Int
-hashExpr e = abs (hash_expr e)
-       -- Negative numbers kill UniqFM
+hashExpr e | hash < 0  = 77    -- Just in case we hit -maxInt
+          | otherwise = hash
+          where
+            hash = abs (hash_expr e)   -- Negative numbers kill UniqFM
 
 hash_expr (Note _ e)                     = hash_expr e
 hash_expr (Let (NonRec b r) e)    = hashId b
 hash_expr (Let (Rec ((b,r):_)) e) = hashId b
 hash_expr (Case _ b _)           = hashId b
-hash_expr (App f e)              = hash_expr f + fast_hash_expr e
+hash_expr (App f e)              = hash_expr f * fast_hash_expr e
 hash_expr (Var v)                = hashId v
-hash_expr (Con con args)         = foldr ((+) . fast_hash_expr) (hashCon con) args
+hash_expr (Lit lit)              = hashLiteral lit
 hash_expr (Lam b _)              = hashId b
-hash_expr (Type t)               = trace "hash_expr: type" 0           -- Shouldn't happen
+hash_expr (Type t)               = trace "hash_expr: type" 1           -- Shouldn't happen
 
 fast_hash_expr (Var v)         = hashId v
-fast_hash_expr (Con con args)  = fast_hash_args args con
+fast_hash_expr (Lit lit)       = hashLiteral lit
 fast_hash_expr (App f (Type _)) = fast_hash_expr f
 fast_hash_expr (App f a)        = fast_hash_expr a
 fast_hash_expr (Lam b _)        = hashId b
-fast_hash_expr other           = 0
-
-fast_hash_args []             con = hashCon con
-fast_hash_args (Type t : args) con = fast_hash_args args con
-fast_hash_args (arg    : args) con = fast_hash_expr arg
+fast_hash_expr other           = 1
 
 hashId :: Id -> Int
 hashId id = hashName (idName id)