[project @ 2003-04-10 14:44:18 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / Simplify.lhs
index 0a30390..2cb43e4 100644 (file)
@@ -21,9 +21,10 @@ import SimplUtils    ( mkCase, mkLam, newId, prepareAlts,
                        )
 import Var             ( mustHaveLocalBinding )
 import VarEnv
-import Id              ( Id, idType, idInfo, idArity, isDataConId, 
+import Id              ( Id, idType, idInfo, idArity, isDataConWorkId, 
                          setIdUnfolding, isDeadBinder,
                          idNewDemandInfo, setIdInfo,
+                         idSpecialisation, setIdSpecialisation,
                          setIdOccInfo, zapLamIdInfo, setOneShotLambda, 
                        )
 import OccName         ( encodeFS )
@@ -49,7 +50,7 @@ import CostCentre     ( currentCCS )
 import Type            ( isUnLiftedType, seqType, tyConAppArgs, funArgTy,
                          splitFunTy_maybe, splitFunTy, eqType
                        )
-import Subst           ( mkSubst, substTy, substExpr,
+import Subst           ( mkSubst, substTy, substExpr, substRules,
                          isInScope, lookupIdSubst, simplIdInfo
                        )
 import TysPrim         ( realWorldStatePrimTy )
@@ -451,24 +452,34 @@ simplLazyBind :: SimplEnv
              -> InExpr -> SimplEnv     -- The RHS and its environment
              -> SimplM (FloatsWith SimplEnv)
 
-simplLazyBind env top_lvl is_rec bndr bndr' rhs rhs_se
-  =    -- Substitute IdInfo on binder, in the light of earlier
-       -- substitutions in this very letrec, and extend the 
-       -- in-scope env, so that the IdInfo for this binder extends 
-       -- over the RHS for the binder itself.
+simplLazyBind env top_lvl is_rec bndr bndr1 rhs rhs_se
+  =    -- Substitute the rules for this binder in the light
+       -- of earlier substitutions in this very letrec group,
+       -- add the substituted rules to the IdInfo, and 
+       -- extend the in-scope env, so that the IdInfo for this 
+       -- binder extends  over the RHS for the binder itself.
        --
        -- This is important.  Manuel found cases where he really, really
        -- wanted a RULE for a recursive function to apply in that function's
-       -- own right-hand side.
+       -- own right-hand side.
        --
        -- NB: does no harm for non-recursive bindings
+       --
+       -- NB2: just rules!  In particular, the arity of an Id is not visible
+       -- in its own RHS, else we eta-reduce
+       --      f = \x -> f x
+       -- to
+       --      f = f
+       -- which isn't sound.  And it makes the arity in f's IdInfo greater than
+       -- the manifest arity, which isn't good.
     let
-       bndr''            = bndr' `setIdInfo` simplIdInfo (getSubst env) (idInfo bndr)
-       env1              = modifyInScope env bndr'' bndr''
+       rules             = idSpecialisation bndr
+       bndr2             = bndr1 `setIdSpecialisation` substRules (getSubst env) rules
+       env1              = modifyInScope env bndr2 bndr2
        rhs_env           = setInScope rhs_se env1
        is_top_level      = isTopLevel top_lvl
        ok_float_unlifted = not is_top_level && isNonRec is_rec
-       rhs_cont          = mkStop (idType bndr') AnRhs
+       rhs_cont          = mkStop (idType bndr1) AnRhs
     in
        -- Simplify the RHS; note the mkStop, which tells 
        -- the simplifier that this is the RHS of a let.
@@ -477,7 +488,7 @@ simplLazyBind env top_lvl is_rec bndr bndr' rhs rhs_se
        -- If any of the floats can't be floated, give up now
        -- (The allLifted predicate says True for empty floats.)
     if (not ok_float_unlifted && not (allLifted floats)) then
-       completeLazyBind env1 top_lvl bndr bndr''
+       completeLazyBind env1 top_lvl bndr bndr2
                         (wrapFloats floats rhs1)
     else       
 
@@ -488,7 +499,7 @@ simplLazyBind env top_lvl is_rec bndr bndr' rhs rhs_se
        -- If the result is a PAP, float the floats out, else wrap them
        -- By this time it's already been ANF-ised (if necessary)
     if isEmptyFloats floats && isNilOL aux_binds then  -- Shortcut a common case
-       completeLazyBind env1 top_lvl bndr bndr'' rhs2
+       completeLazyBind env1 top_lvl bndr bndr2 rhs2
 
        -- We use exprIsTrivial here because we want to reveal lone variables.  
        -- E.g.  let { x = letrec { y = E } in y } in ...
@@ -507,19 +518,19 @@ simplLazyBind env top_lvl is_rec bndr bndr' rhs rhs_se
                -- There's a subtlety here.  There may be a binding (x* = e) in the
                -- floats, where the '*' means 'will be demanded'.  So is it safe
                -- to float it out?  Answer no, but it won't matter because
-               -- we only float if arg' is a WHNF,
+               -- we only float if (a) arg' is a WHNF, or (b) it's going to top level
                -- and so there can't be any 'will be demanded' bindings in the floats.
-               -- Hence the assert
-        WARN( any demanded_float (floatBinds floats), 
+               -- Hence the warning
+        WARN( not is_top_level && any demanded_float (floatBinds floats), 
              ppr (filter demanded_float (floatBinds floats)) )
 
        tick LetFloatFromLet                    `thenSmpl_` (
        addFloats env1 floats                   $ \ env2 ->
        addAtomicBinds env2 (fromOL aux_binds)  $ \ env3 ->
-       completeLazyBind env3 top_lvl bndr bndr'' rhs2)
+       completeLazyBind env3 top_lvl bndr bndr2 rhs2)
 
     else
-       completeLazyBind env1 top_lvl bndr bndr'' (wrapFloats floats rhs1)
+       completeLazyBind env1 top_lvl bndr bndr2 (wrapFloats floats rhs1)
 
 #ifdef DEBUG
 demanded_float (NonRec b r) = isStrictDmd (idNewDemandInfo b) && not (isUnLiftedType (idType b))
@@ -692,8 +703,8 @@ simplExprF env (Case scrut bndr alts) cont
 
 simplExprF env (Let (Rec pairs) body) cont
   = simplRecBndrs env (map fst pairs)          `thenSmpl` \ (env, bndrs') -> 
-       -- NB: bndrs' don't have unfoldings or spec-envs
-       -- We add them as we go down, using simplPrags
+       -- NB: bndrs' don't have unfoldings or rules
+       -- We add them as we go down
 
     simplRecBind env NotTopLevel pairs bndrs'  `thenSmpl` \ (floats, env) ->
     addFloats env floats                       $ \ env ->
@@ -795,12 +806,14 @@ simplNote env (Coerce to from) body cont
                                                -- the inner one is redundant
 
        addCoerce t1t2 s1s2 (ApplyTo dup arg arg_se cont)
-         | Just (s1, s2) <- splitFunTy_maybe s1s2
+         | not (isTypeArg arg),        -- This whole case only works for value args
+                                       -- Could upgrade to have equiv thing for type apps too  
+           Just (s1, s2) <- splitFunTy_maybe s1s2
                --      (coerce (T1->T2) (S1->S2) F) E
                -- ===> 
                --      coerce T2 S2 (F (coerce S1 T1 E))
                --
-               -- t1t2 must be a function type, T1->T2
+               -- t1t2 must be a function type, T1->T2, because it's applied to something
                -- but s1s2 might conceivably not be
                --
                -- When we build the ApplyTo we can't mix the out-types
@@ -840,6 +853,10 @@ simplNote env InlineMe e cont
                -- an interesting context of any kind to combine with
                -- (even a type application -- anything except Stop)
   = simplExprF env e cont
+
+simplNote env (CoreNote s) e cont
+  = simplExpr env e    `thenSmpl` \ e' ->
+    rebuild env (Note (CoreNote s) e') cont
 \end{code}
 
 
@@ -1045,11 +1062,14 @@ simplifyArg env fn_ty (val_arg, arg_se, is_strict) cont_ty thing_inside
   | is_strict 
   = simplStrictArg AnArg env val_arg arg_se arg_ty cont_ty thing_inside
 
-  | otherwise
-  = simplExprF (setInScope arg_se env) val_arg
-              (mkStop arg_ty AnArg)            `thenSmpl` \ (floats, arg1) ->
-    addFloats env floats                       $ \ env ->
-    thing_inside env arg1
+  | otherwise  -- Lazy argument
+               -- DO NOT float anything outside, hence simplExprC
+               -- There is no benefit (unlike in a let-binding), and we'd
+               -- have to be very careful about bogus strictness through 
+               -- floating a demanded let.
+  = simplExprC (setInScope arg_se env) val_arg
+              (mkStop arg_ty AnArg)            `thenSmpl` \ arg1 ->
+   thing_inside env arg1
   where
     arg_ty = funArgTy fn_ty
 
@@ -1126,8 +1146,8 @@ mkAtomicArgs :: Bool      -- A strict binding
                                                  -- if the strict-binding flag is on
 
 mkAtomicArgs is_strict ok_float_unlifted rhs
-  | (Var fun, args) <- collectArgs rhs,                        -- It's an application
-    isDataConId fun || valArgCount args < idArity fun  -- And it's a constructor or PAP
+  | (Var fun, args) <- collectArgs rhs,                                -- It's an application
+    isDataConWorkId fun || valArgCount args < idArity fun      -- And it's a constructor or PAP
   = go fun nilOL [] args       -- Have a go
 
   | otherwise = bale_out       -- Give up