[project @ 1997-05-18 23:26:46 by sof]
[ghc-hetmet.git] / ghc / compiler / simplCore / SimplUtils.lhs
index f546fbc..4b8f01a 100644 (file)
@@ -10,7 +10,7 @@ module SimplUtils (
 
        floatExposesHNF,
 
-       mkTyLamTryingEta, mkValLamTryingEta,
+       etaCoreExpr,
 
        etaExpandCount,
 
@@ -21,26 +21,28 @@ module SimplUtils (
        type_ok_for_let_to_case
     ) where
 
-import Ubiq{-uitous-}
+IMP_Ubiq(){-uitous-}
+IMPORT_DELOOPER(SmplLoop)              -- paranoia checking
 
 import BinderInfo
-import CmdLineOpts     ( SimplifierSwitch(..) )
+import CmdLineOpts     ( opt_DoEtaReduction, SimplifierSwitch(..) )
 import CoreSyn
-import CoreUtils       ( manifestlyWHNF )
-import Id              ( idType, isBottomingId, idWantsToBeINLINEd,
+import CoreUnfold      ( SimpleUnfolding, mkFormSummary, FormSummary(..) )
+import Id              ( idType, isBottomingId, idWantsToBeINLINEd, dataConArgTys,
                          getIdArity, GenId{-instance Eq-}
                        )
-import IdInfo          ( arityMaybe )
+import IdInfo          ( ArityInfo(..) )
 import Maybes          ( maybeToBool )
-import PrelInfo                ( augmentId, buildId, realWorldStateTy )
+import PrelVals                ( augmentId, buildId )
 import PrimOp          ( primOpIsCheap )
 import SimplEnv
 import SimplMonad
-import Type            ( eqTy, isPrimType, maybeAppDataTyCon, getTyVar_maybe )
-import TyVar           ( GenTyVar{-instance Eq-} )
+import Type            ( tyVarsOfType, isPrimType, maybeAppDataTyConExpandingDicts )
+import TysWiredIn      ( realWorldStateTy )
+import TyVar           ( elementOfTyVarSet,
+                         GenTyVar{-instance Eq-} )
 import Util            ( isIn, panic )
 
-getInstantiatedDataConSig =  panic "SimplUtils.getInstantiatedDataConSig (ToDo)"
 \end{code}
 
 
@@ -75,8 +77,11 @@ floatExposesHNF float_lets float_primops ok_to_dup rhs
     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,12 +103,16 @@ floatExposesHNF float_lets float_primops ok_to_dup rhs
     try_deflt (BindDefault _ rhs) = try rhs
 \end{code}
 
+Eta reduction
+~~~~~~~~~~~~~
+@etaCoreExpr@ trys an eta reduction at the top level of a Core Expr.
 
-Eta reduction on ordinary lambdas
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-We have a go at doing
+e.g.   \ x y -> f x y  ===>  f
 
-       \ 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
@@ -119,43 +128,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.
 
-\begin{code}
-mkValLamTryingEta :: [Id]              -- Args to the lambda
-              -> CoreExpr              -- Lambda body
-              -> CoreExpr
+Doing eta on type lambdas is useful too:
 
-mkValLamTryingEta [] body = body
+       /\a -> <expr> a    ===>     <expr>
 
-mkValLamTryingEta orig_ids body
-  = reduce_it (reverse orig_ids) body
-  where
-    bale_out = mkValLam orig_ids body
+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:
 
-    reduce_it [] residual
-      | residual_ok residual = residual
-      | otherwise           = bale_out
+       /\ a -> f Char# a       =NO=> f Char#
 
-    reduce_it (id:ids) (App fun (VarArg arg))
-      | id == arg
-      && not (idType id `eqTy` realWorldStateTy)
-        -- *never* eta-reduce away a PrimIO state token! (WDP 94/11)
-      = reduce_it ids fun
+\begin{code}
+etaCoreExpr :: CoreExpr -> CoreExpr
 
-    reduce_it ids other = bale_out
 
-    is_elem = isIn "mkValLamTryingEta"
+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
+    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 (v `is_elem` orig_ids)
-                         -- Fun mustn't be one of the bound ids
+    residual_ok (Var v)
+       = not (eta_match bndr (VarArg v))
     residual_ok (App fun arg)
-      | notValArg arg  = residual_ok fun
-    residual_ok other  = False
+       | 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
 ~~~~~~~~~~~~~
@@ -214,12 +255,7 @@ eta_fun expr@(Var v)
   | isBottomingId v            -- Bottoming ids have "infinite arity"
   = 10000                      -- Blargh.  Infinite enough!
 
-eta_fun expr@(Var 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
 \end{code}
@@ -247,12 +283,13 @@ which aren't WHNF but are ``cheap'' are:
 \begin{code}
 manifestlyCheap :: GenCoreExpr bndr Id tv uv -> Bool
 
-manifestlyCheap (Var _)     = True
-manifestlyCheap (Lit _)     = True
-manifestlyCheap (Con _ _)   = True
-manifestlyCheap (SCC _ e)   = manifestlyCheap e
-manifestlyCheap (Lam x e)   = if isValBinder x then True else manifestlyCheap e
-manifestlyCheap (Prim op _) = primOpIsCheap op
+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 (Let bind body)
   = manifestlyCheap body && all manifestlyCheap (rhssOfBind bind)
@@ -275,78 +312,14 @@ manifestlyCheap other_expr   -- look for manifest partial application
               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
+              num_val_args < idMinArity f
 
       _ -> False
     }
-\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}
-mkTyLamTryingEta :: [TyVar] -> CoreExpr -> CoreExpr
-
-mkTyLamTryingEta 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
-       mkTyLam tyvars tylam_body
-  where
-    (tyvar_args, fun) = strip_tyvar_args [] tylam_body
-
-    strip_tyvar_args args_so_far tyapp@(App fun (TyArg ty))
-      = case getTyVar_maybe 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 (App _ (UsageArg _))
-      = panic "SimplUtils.mkTyLamTryingEta: strip_tyvar_args UsageArg"
-
-    strip_tyvar_args args_so_far fun
-      = (args_so_far, fun)
-
-    check_fun (Var f) = True    -- Claim: tyvars not mentioned by type of f
-    check_fun other     = False
 \end{code}
 
+
 Let to case
 ~~~~~~~~~~~
 
@@ -372,10 +345,10 @@ mkIdentityAlts rhs_ty
     returnSmpl (PrimAlts [] (BindDefault (binder, bad_occ_info) (Var binder)))
 
   | otherwise
-  = case (maybeAppDataTyCon rhs_ty) of
+  = 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
@@ -402,10 +375,15 @@ simplIdWantsToBeINLINEd id env
     then False
     else idWantsToBeINLINEd id
 
+idMinArity id = case getIdArity id of
+                       UnknownArity   -> 0
+                       ArityAtLeast n -> n
+                       ArityExactly n -> n
+
 type_ok_for_let_to_case :: Type -> Bool
 
 type_ok_for_let_to_case ty
-  = case (maybeAppDataTyCon ty) of
+  = case (maybeAppDataTyConExpandingDicts ty) of
       Nothing                                   -> False
       Just (tycon, ty_args, [])                 -> False
       Just (tycon, ty_args, non_null_data_cons) -> True