[project @ 2001-02-28 11:42:09 by simonpj]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CoreUtils.lhs
index 729b54f..c209cc8 100644 (file)
@@ -10,11 +10,14 @@ module CoreUtils (
        bindNonRec, mkIfThenElse, mkAltExpr,
         mkPiType,
 
+       -- Taking expressions apart
+       findDefault, findAlt,
+
        -- Properties of expressions
        exprType, coreAltsType, 
        exprIsBottom, exprIsDupable, exprIsTrivial, exprIsCheap, 
        exprIsValue,exprOkForSpeculation, exprIsBig, 
-       exprIsConApp_maybe,
+       exprIsConApp_maybe, exprIsAtom,
        idAppIsBottom, idAppIsCheap,
        exprArity,
 
@@ -50,7 +53,7 @@ import PrimOp         ( primOpOkForSpeculation, primOpIsCheap,
                          primOpIsDupable )
 import Id              ( Id, idType, idFlavour, idStrictness, idLBVarInfo, 
                          mkWildId, idArity, idName, idUnfolding, idInfo, 
-                         isDataConId_maybe, isPrimOpId_maybe, mkSysLocal
+                         isDataConId_maybe, isPrimOpId_maybe, mkSysLocal, hasNoBinding
                        )
 import IdInfo          ( LBVarInfo(..),  
                          IdFlavour(..),
@@ -156,9 +159,26 @@ Drop trivial InlineMe's.  This is somewhat important, because if we have an unfo
 that looks like        (Note InlineMe (Var v)), the InlineMe doesn't go away because it may
 not be *applied* to anything.
 
+We don't use exprIsTrivial here, though, because we sometimes generate worker/wrapper
+bindings like
+       fw = ...
+       f  = inline_me (coerce t fw)
+As usual, the inline_me prevents the worker from getting inlined back into the wrapper.
+We want the split, so that the coerces can cancel at the call site.  
+
+However, we can get left with tiresome type applications.  Notably, consider
+       f = /\ a -> let t = e in (t, w)
+Then lifting the let out of the big lambda gives
+       t' = /\a -> e
+       f = /\ a -> let t = inline_me (t' a) in (t, w)
+The inline_me is to stop the simplifier inlining t' right back
+into t's RHS.  In the next phase we'll substitute for t (since
+its rhs is trivial) and *then* we could get rid of the inline_me.
+But it hardly seems worth it, so I don't bother.
+
 \begin{code}
-mkInlineMe e | exprIsTrivial e = e
-            | otherwise       = Note InlineMe e
+mkInlineMe (Var v) = Var v
+mkInlineMe e      = Note InlineMe e
 \end{code}
 
 
@@ -225,6 +245,35 @@ mkIfThenElse guard then_expr else_expr
           (DataAlt falseDataCon, [], else_expr) ]
 \end{code}
 
+
+%************************************************************************
+%*                                                                     *
+\subsection{Taking expressions apart}
+%*                                                                     *
+%************************************************************************
+
+
+\begin{code}
+findDefault :: [CoreAlt] -> ([CoreAlt], Maybe CoreExpr)
+findDefault []                         = ([], Nothing)
+findDefault ((DEFAULT,args,rhs) : alts) = ASSERT( null alts && null args ) 
+                                         ([], Just rhs)
+findDefault (alt : alts)               = case findDefault alts of 
+                                           (alts', deflt) -> (alt : alts', deflt)
+
+findAlt :: AltCon -> [CoreAlt] -> CoreAlt
+findAlt con alts
+  = go alts
+  where
+    go []          = pprPanic "Missing alternative" (ppr con $$ vcat (map ppr alts))
+    go (alt : alts) | matches alt = alt
+                   | otherwise   = go alts
+
+    matches (DEFAULT, _, _) = True
+    matches (con1, _, _)    = con == con1
+\end{code}
+
+
 %************************************************************************
 %*                                                                     *
 \subsection{Figuring out things about expressions}
@@ -241,7 +290,17 @@ mkIfThenElse guard then_expr else_expr
 
 \begin{code}
 exprIsTrivial (Var v)
-  | Just op <- isPrimOpId_maybe v      = primOpIsDupable op
+  | hasNoBinding v                    = idArity v == 0
+       -- WAS: | Just op <- isPrimOpId_maybe v      = primOpIsDupable op
+       -- The idea here is that a constructor worker, like $wJust, is
+       -- really short for (\x -> $wJust x), becuase $wJust has no binding.
+       -- So it should be treated like a lambda.
+       -- Ditto unsaturated primops.
+       -- This came up when dealing with eta expansion/reduction for
+       --      x = $wJust
+       -- Here we want to eta-expand.  This looks like an optimisation,
+       -- but it's important (albeit tiresome) that CoreSat doesn't increase 
+       -- anything's arity
   | otherwise                          = True
 exprIsTrivial (Type _)                = True
 exprIsTrivial (Lit lit)               = True
@@ -249,6 +308,15 @@ exprIsTrivial (App e arg)                 = isTypeArg arg && exprIsTrivial e
 exprIsTrivial (Note _ e)              = exprIsTrivial e
 exprIsTrivial (Lam b body) | isTyVar b = exprIsTrivial body
 exprIsTrivial other                   = False
+
+exprIsAtom :: CoreExpr -> Bool
+-- Used to decide whether to let-binding an STG argument
+-- when compiling to ILX => type applications are not allowed
+exprIsAtom (Var v)    = True   -- primOpIsDupable?
+exprIsAtom (Lit lit)  = True
+exprIsAtom (Type ty)  = True
+exprIsAtom (Note _ e) = exprIsAtom e
+exprIsAtom other      = False
 \end{code}
 
 
@@ -441,7 +509,17 @@ evaluated to WHNF.  This is used to decide wether it's ok to change
 
 and to decide whether it's safe to discard a `seq`
 
-So, it does *not* treat variables as evaluated, unless they say they are
+So, it does *not* treat variables as evaluated, unless they say they are.
+
+But it *does* treat partial applications and constructor applications
+as values, even if their arguments are non-trivial; 
+       e.g.  (:) (f x) (map f xs)      is a value
+             map (...redex...)         is a value
+Because `seq` on such things completes immediately
+
+A worry: constructors with unboxed args:
+               C (f x :: Int#)
+Suppose (f x) diverges; then C (f x) is not a value.
 
 \begin{code}
 exprIsValue :: CoreExpr -> Bool                -- True => Value-lambda, constructor, PAP
@@ -480,18 +558,17 @@ 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
+       | Just con <- isDataConId_maybe fun,
+         length args >= dataConRepArity con
+               -- Might be > because the arity excludes type args
+       = Just (con,args)
 
+       -- Look through unfoldings, but only cheap ones, because
+       -- we are effectively duplicating the unfolding
     analyse (Var fun, [])
-       = case maybeUnfoldingTemplate (idUnfolding fun) of
-               Nothing  -> Nothing
-               Just unf -> exprIsConApp_maybe unf
+       | let unf = idUnfolding fun,
+         isCheapUnfolding unf
+       = exprIsConApp_maybe (unfoldingTemplate unf)
 
     analyse other = Nothing
 \end{code}