[project @ 2001-05-22 13:43:14 by simonpj]
[ghc-hetmet.git] / ghc / compiler / coreSyn / CoreUtils.lhs
index 6905cb7..7241e08 100644 (file)
@@ -49,11 +49,10 @@ import VarEnv
 import Name            ( hashName )
 import Literal         ( hashLiteral, literalType, litIsDupable )
 import DataCon         ( DataCon, dataConRepArity )
-import PrimOp          ( primOpOkForSpeculation, primOpIsCheap, 
-                         primOpIsDupable )
+import PrimOp          ( primOpOkForSpeculation, primOpIsCheap )
 import Id              ( Id, idType, globalIdDetails, idStrictness, idLBVarInfo, 
                          mkWildId, idArity, idName, idUnfolding, idInfo, isOneShotLambda,
-                         isDataConId_maybe, isPrimOpId_maybe, mkSysLocal, hasNoBinding
+                         isDataConId_maybe, mkSysLocal, hasNoBinding
                        )
 import IdInfo          ( LBVarInfo(..),  
                          GlobalIdDetails(..),
@@ -66,7 +65,6 @@ import Type           ( Type, mkFunTy, mkForAllTy, splitFunTy_maybe,
 import TysWiredIn      ( boolTy, trueDataCon, falseDataCon )
 import CostCentre      ( CostCentre )
 import UniqSupply      ( UniqSupply, splitUniqSupply, uniqFromSupply )
-import Maybes          ( maybeToBool )
 import Outputable
 import TysPrim         ( alphaTy )     -- Debugging only
 \end{code}
@@ -199,11 +197,12 @@ mkCoerce to_ty from_ty expr
 \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
+       --       cost centre stack profiling
+mkSCC cc (Lit lit)         = Lit lit
+mkSCC cc (Lam x e)         = Lam x (mkSCC cc e)  -- Move _scc_ inside lambda
+mkSCC cc (Note (SCC cc') e) = Note (SCC cc) (Note (SCC cc') e)
+mkSCC cc (Note n e)        = Note n (mkSCC cc e) -- Move _scc_ inside notes
+mkSCC cc expr              = Note (SCC cc) expr
 \end{code}
 
 
@@ -333,10 +332,11 @@ exprIsAtom other      = False
 
 
 \begin{code}
-exprIsDupable (Type _)      = True
-exprIsDupable (Var v)       = True
-exprIsDupable (Lit lit)      = litIsDupable lit
-exprIsDupable (Note _ e)     = exprIsDupable e
+exprIsDupable (Type _)         = True
+exprIsDupable (Var v)          = True
+exprIsDupable (Lit lit)        = litIsDupable lit
+exprIsDupable (Note InlineMe e) = True
+exprIsDupable (Note _ e)        = exprIsDupable e
 exprIsDupable expr          
   = go expr 0
   where
@@ -383,6 +383,7 @@ exprIsCheap :: CoreExpr -> Bool
 exprIsCheap (Lit lit)            = True
 exprIsCheap (Type _)             = True
 exprIsCheap (Var _)              = True
+exprIsCheap (Note InlineMe e)            = True
 exprIsCheap (Note _ e)           = exprIsCheap e
 exprIsCheap (Lam x e)            = if isId x then True else exprIsCheap e
 exprIsCheap (Case e _ alts)       = exprIsCheap e && 
@@ -518,9 +519,11 @@ as values, even if their arguments are non-trivial;
              map (...redex...)         is a value
 Because `seq` on such things completes immediately
 
-A worry: constructors with unboxed args:
+A possible worry: constructors with unboxed args:
                C (f x :: Int#)
-Suppose (f x) diverges; then C (f x) is not a value.
+Suppose (f x) diverges; then C (f x) is not a value.  True, but
+this form is illegal (see the invariants in CoreSyn).  Args of unboxed
+type must be ok-for-speculation (or trivial).
 
 \begin{code}
 exprIsValue :: CoreExpr -> Bool                -- True => Value-lambda, constructor, PAP
@@ -555,8 +558,13 @@ idAppIsValue id n_val_args
 
 \begin{code}
 exprIsConApp_maybe :: CoreExpr -> Maybe (DataCon, [CoreExpr])
-exprIsConApp_maybe expr
-  = analyse (collectArgs expr)
+exprIsConApp_maybe (Note InlineMe expr) = exprIsConApp_maybe expr
+    -- We ignore InlineMe notes in case we have
+    -- x = __inline_me__ (a,b)
+    -- All part of making sure that INLINE pragmas never hurt
+    -- Marcin tripped on this one when making dictionaries more inlinable
+
+exprIsConApp_maybe expr = analyse (collectArgs expr)
   where
     analyse (Var fun, args)
        | Just con <- isDataConId_maybe fun,
@@ -574,20 +582,6 @@ exprIsConApp_maybe expr
     analyse other = Nothing
 \end{code}
 
-The arity of an expression (in the code-generator sense, i.e. the
-number of lambdas at the beginning).
-
-\begin{code}
-exprArity :: CoreExpr -> Int
-exprArity (Lam x e)
-  | isTyVar x = exprArity e
-  | otherwise = 1 + exprArity e
-exprArity (Note _ e)
-  -- Ignore coercions.   Top level sccs are removed by the final 
-  -- profiling pass, so we ignore those too.
-  = exprArity e
-exprArity _ = 0
-\end{code}
 
 
 %************************************************************************
@@ -648,7 +642,8 @@ exprEtaExpandArity :: CoreExpr -> (Int, Bool)
 --
 -- Consider    let x = expensive in \y z -> E
 -- We want this to have arity 2 if the \y-abstraction is a 1-shot lambda
--- Hence the extra Bool returned by go1
+-- 
+-- Hence the list of Bools returned by go1
 --     NB: this is particularly important/useful for IO state 
 --     transformers, where we often get
 --             let x = E in \ s -> ...
@@ -676,7 +671,7 @@ exprEtaExpandArity e
     go1 (Note n e) | ok_note n = go1 e
     go1 (Var v)                        = replicate (idArity v) False   -- When the type of the Id
                                                                -- encodes one-shot-ness, use
-                                                               -- th iinfo here
+                                                               -- the idinfo here
 
        -- Lambdas; increase arity
     go1 (Lam x e)  | isId x     = isOneShotLambda x : go1 e
@@ -703,7 +698,7 @@ exprEtaExpandArity e
     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
+           -- This may seem surprising, but consider
            --  f = _inline_me (\x -> e)
            -- We DO NOT want to eta expand this to
            --  f = \x -> (_inline_me (\x -> e)) x
@@ -743,8 +738,6 @@ etaExpand :: Int            -- Add this number of value args
 -- would return
 --     (/\b. coerce T (\y::A -> (coerce (A->B) (E b) y)
 
--- (case x of { I# x -> /\ a -> coerce T E)
-
 etaExpand n us expr ty
   | n == 0     -- Saturated, so nothing to do
   = expr
@@ -772,6 +765,42 @@ etaExpand n us expr ty
 \end{code}
 
 
+exprArity is a cheap-and-cheerful version of exprEtaExpandArity.
+It tells how many things the expression can be applied to before doing
+any work.  It doesn't look inside cases, lets, etc.  The idea is that
+exprEtaExpandArity will do the hard work, leaving something that's easy
+for exprArity to grapple with.  In particular, Simplify uses exprArity to
+compute the ArityInfo for the Id. 
+
+Originally I thought that it was enough just to look for top-level lambdas, but
+it isn't.  I've seen this
+
+       foo = PrelBase.timesInt
+
+We want foo to get arity 2 even though the eta-expander will leave it
+unchanged, in the expectation that it'll be inlined.  But occasionally it
+isn't, because foo is blacklisted (used in a rule).  
+
+Similarly, see the ok_note check in exprEtaExpandArity.  So 
+       f = __inline_me (\x -> e)
+won't be eta-expanded.
+
+And in any case it seems more robust to have exprArity be a bit more intelligent.
+
+\begin{code}
+exprArity :: CoreExpr -> Int
+exprArity e = go e `max` 0
+           where
+             go (Lam x e) | isId x    = go e + 1
+                          | otherwise = go e
+             go (Note _ e)            = go e
+             go (App e (Type t))      = go e
+             go (App f a)             = go f - 1
+             go (Var v)               = idArity v
+             go _                     = 0
+\end{code}
+
+
 %************************************************************************
 %*                                                                     *
 \subsection{Equality}