update submodule pointer
[ghc-hetmet.git] / compiler / specialise / SpecConstr.lhs
index 8e08169..6cc05a3 100644 (file)
@@ -33,9 +33,9 @@ import CoreMonad
 import HscTypes         ( ModGuts(..) )
 import WwLib           ( mkWorkerArgs )
 import DataCon
-import Coercion        
+import Coercion                hiding( substTy, substCo )
 import Rules
-import Type            hiding( substTy )
+import Type            hiding ( substTy )
 import Id
 import MkCore          ( mkImpossibleExpr )
 import Var
@@ -50,6 +50,7 @@ import Demand
 import DmdAnal         ( both )
 import Serialized       ( deserializeWithData )
 import Util
+import Pair
 import UniqSupply
 import Outputable
 import FastString
@@ -386,6 +387,18 @@ specialising the loops arising from stream fusion, for example in NDP where
 we were getting literally hundreds of (mostly unused) specialisations of
 a local function.
 
+In a case like the above we end up never calling the original un-specialised
+function.  (Although we still leave its code around just in case.)
+
+However, if we find any boring calls in the body, including *unsaturated*
+ones, such as
+      letrec foo x y = ....foo...
+      in map foo xs
+then we will end up calling the un-specialised function, so then we *should*
+use the calls in the un-specialised RHS as seeds.  We call these "boring 
+call patterns, and callsToPats reports if it finds any of these.
+
+
 Note [Do not specialise diverging functions]
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 Specialising a function that just diverges is a waste of code.
@@ -687,6 +700,9 @@ scSubstId env v = lookupIdSubst (text "scSubstId") (sc_subst env) v
 scSubstTy :: ScEnv -> Type -> Type
 scSubstTy env ty = substTy (sc_subst env) ty
 
+scSubstCo :: ScEnv -> Coercion -> Coercion
+scSubstCo env co = substCo (sc_subst env) co
+
 zapScSubst :: ScEnv -> ScEnv
 zapScSubst env = env { sc_subst = zapSubstEnv (sc_subst env) }
 
@@ -749,7 +765,7 @@ extendCaseBndrs env scrut case_bndr con alt_bndrs
    live_case_bndr = not (isDeadBinder case_bndr)
    env1 | Var v <- scrut = extendValEnv env v cval
         | otherwise      = env -- See Note [Add scrutinee to ValueEnv too]
-   env2 | live_case_bndr = extendValEnv env case_bndr cval
+   env2 | live_case_bndr = extendValEnv env1 case_bndr cval
         | otherwise      = env1
 
    alt_bndrs' | case scrut of { Var {} -> True; _ -> live_case_bndr }
@@ -765,7 +781,7 @@ extendCaseBndrs env scrut case_bndr con alt_bndrs
                        vanilla_args = map Type (tyConAppArgs (idType case_bndr)) ++
                                       varsToCoreExprs alt_bndrs
 
-   zap v | isTyCoVar v = v             -- See NB2 above
+   zap v | isTyVar v = v               -- See NB2 above
          | otherwise = zapIdOccInfo v
 
 
@@ -981,15 +997,16 @@ scExpr env e = scExpr' env e
 
 
 scExpr' env (Var v)     = case scSubstId env v of
-                           Var v' -> return (varUsage env v' UnkOcc, Var v')
+                           Var v' -> return (mkVarUsage env v' [], Var v')
                            e'     -> scExpr (zapScSubst env) e'
 
 scExpr' env (Type t)    = return (nullUsage, Type (scSubstTy env t))
+scExpr' env (Coercion c) = return (nullUsage, Coercion (scSubstCo env c))
 scExpr' _   e@(Lit {})  = return (nullUsage, e)
 scExpr' env (Note n e)  = do (usg,e') <- scExpr env e
                              return (usg, Note n e')
 scExpr' env (Cast e co) = do (usg, e') <- scExpr env e
-                             return (usg, Cast e' (scSubstTy env co))
+                             return (usg, Cast e' (scSubstCo env co))
 scExpr' env e@(App _ _) = scApp env (collectArgs e)
 scExpr' env (Lam b e)   = do let (env', b') = extendBndr env b
                              (usg, e') <- scExpr env' e
@@ -1035,7 +1052,7 @@ scExpr' env (Case scrut b ty alts)
           ; return (usg', b_occ `combineOcc` scrut_occ, (con, bs2, rhs')) }
 
 scExpr' env (Let (NonRec bndr rhs) body)
-  | isTyCoVar bndr     -- Type-lets may be created by doBeta
+  | isTyVar bndr       -- Type-lets may be created by doBeta
   = scExpr' (extendScSubst env bndr rhs) body
 
   | otherwise  
@@ -1118,7 +1135,7 @@ scApp env (Var fn, args)  -- Function is a variable
            fn'@(Lam {}) -> scExpr (zapScSubst env) (doBeta fn' args')
                        -- Do beta-reduction and try again
 
-           Var fn' -> return (arg_usg `combineUsage` mk_fn_usg fn' args',
+           Var fn' -> return (arg_usg `combineUsage` mkVarUsage env fn' args',
                                mkApps (Var fn') args')
 
            other_fn' -> return (arg_usg, mkApps other_fn' args') }
@@ -1131,14 +1148,6 @@ scApp env (Var fn, args) -- Function is a variable
     doBeta (Lam bndr body) (arg : args) = Let (NonRec bndr arg) (doBeta body args)
     doBeta fn             args         = mkApps fn args
 
-    mk_fn_usg fn' args'
-      = case lookupHowBound env fn' of
-         Just RecFun -> SCU { scu_calls = unitVarEnv fn' [(sc_vals env, args')]
-                                , scu_occs  = emptyVarEnv }
-         Just RecArg -> SCU { scu_calls = emptyVarEnv
-                            , scu_occs  = unitVarEnv fn' evalScrutOcc }
-         Nothing     -> nullUsage
-
 -- The function is almost always a variable, but not always.  
 -- In particular, if this pass follows float-in,
 -- which it may, we can get 
@@ -1149,6 +1158,20 @@ scApp env (other_fn, args)
        ; return (combineUsages arg_usgs `combineUsage` fn_usg, mkApps fn' args') }
 
 ----------------------
+mkVarUsage :: ScEnv -> Id -> [CoreExpr] -> ScUsage
+mkVarUsage env fn args
+  = case lookupHowBound env fn of
+       Just RecFun -> SCU { scu_calls = unitVarEnv fn [(sc_vals env, args)]
+                          , scu_occs  = emptyVarEnv }
+       Just RecArg -> SCU { scu_calls = emptyVarEnv
+                          , scu_occs  = unitVarEnv fn arg_occ }
+        Nothing     -> nullUsage
+  where
+    -- I rather think we could use UnkOcc all the time
+    arg_occ | null args = UnkOcc
+            | otherwise = evalScrutOcc
+
+----------------------
 scTopBind :: ScEnv -> CoreBind -> UniqSM (ScEnv, CoreBind)
 scTopBind env (Rec prs)
   | Just threshold <- sc_size env
@@ -1206,13 +1229,6 @@ specInfoBinds (RI fn new_rhs _ _ _) (SI specs _ _)
              -- And now the original binding
   where
     rules = [r | OS _ r _ _ <- specs]
-
-----------------------
-varUsage :: ScEnv -> OutVar -> ArgOcc -> ScUsage
-varUsage env v use 
-  | Just RecArg <- lookupHowBound env v = SCU { scu_calls = emptyVarEnv 
-                                             , scu_occs = unitVarEnv v use }
-  | otherwise                          = nullUsage
 \end{code}
 
 
@@ -1233,10 +1249,13 @@ data SpecInfo = SI [OneSpec]            -- The specialisations we have generated
 
                   Int                  -- Length of specs; used for numbering them
 
-                  (Maybe ScUsage)      -- Nothing => we have generated specialisations
-                                       --            from calls in the *original* RHS
-                                       -- Just cs => we haven't, and this is the usage
-                                       --            of the original RHS
+                  (Maybe ScUsage)      -- Just cs  => we have not yet used calls in the
+                                       --             from calls in the *original* RHS as
+                                       --             seeds for new specialisations;
+                                       --             if you decide to do so, here is the
+                                       --             RHS usage (which has not yet been
+                                       --             unleashed)
+                                       -- Nothing => we have
                                        -- See Note [Local recursive groups]
 
        -- One specialisation: Rule plus definition
@@ -1294,8 +1313,10 @@ specialise env bind_calls (RI fn _ arg_bndrs body arg_occs)
               spec_count' = n_pats + spec_count
        ; case sc_count env of
            Just max | not (sc_force env) && spec_count' > max
-               -> pprTrace "SpecConstr" msg $  
-                   return (nullUsage, spec_info)
+               -> if (debugIsOn || opt_PprStyle_Debug)  -- Suppress this scary message for
+                   then pprTrace "SpecConstr" msg $     -- ordinary users!  Trac #5125
+                        return (nullUsage, spec_info)
+                   else return (nullUsage, spec_info)
                where
                   msg = vcat [ sep [ ptext (sLit "Function") <+> quotes (ppr fn)
                                    , nest 2 (ptext (sLit "has") <+> 
@@ -1403,6 +1424,7 @@ calcSpecStrictness fn qvars pats
     dmd_env = go emptyVarEnv dmds pats
 
     go env ds (Type {} : pats) = go env ds pats
+    go env ds (Coercion {} : pats) = go env ds pats
     go env (d:ds) (pat : pats) = go (go_one env d pat) ds pats
     go env _      _            = env
 
@@ -1503,7 +1525,7 @@ callToPats env bndr_occs (con_env, args)
                -- at the call site
                -- See Note [Shadowing] at the top
                
-             (tvs, ids) = partition isTyCoVar qvars
+             (tvs, ids) = partition isTyVar qvars
              qvars'     = tvs ++ ids
                -- Put the type variables first; the type of a term
                -- variable may mention a type variable
@@ -1538,6 +1560,9 @@ argToPat :: ScEnv
 
 argToPat _env _in_scope _val_env arg@(Type {}) _arg_occ
   = return (False, arg)
+    
+argToPat _env _in_scope _val_env arg@(Coercion {}) _arg_occ
+  = return (False, arg)
 
 argToPat env in_scope val_env (Note _ arg) arg_occ
   = argToPat env in_scope val_env arg arg_occ
@@ -1563,8 +1588,8 @@ argToPat env in_scope val_env (Case scrut _ _ [(_, _, rhs)]) arg_occ
 -}
 
 argToPat env in_scope val_env (Cast arg co) arg_occ
-  | isIdentityCoercion co     -- Substitution in the SpecConstr itself
-                              -- can lead to identity coercions
+  | isReflCo co     -- Substitution in the SpecConstr itself
+                    -- can lead to identity coercions
   = argToPat env in_scope val_env arg arg_occ
   | not (ignoreType env ty2)
   = do { (interesting, arg') <- argToPat env in_scope val_env arg arg_occ
@@ -1574,10 +1599,10 @@ argToPat env in_scope val_env (Cast arg co) arg_occ
        { -- Make a wild-card pattern for the coercion
          uniq <- getUniqueUs
        ; let co_name = mkSysTvName uniq (fsLit "sg")
-             co_var = mkCoVar co_name (mkCoKind ty1 ty2)
-       ; return (interesting, Cast arg' (mkTyVarTy co_var)) } }
+             co_var = mkCoVar co_name (mkCoType ty1 ty2)
+       ; return (interesting, Cast arg' (mkCoVarCo co_var)) } }
   where
-    (ty1, ty2) = coercionKind co
+    Pair ty1 ty2 = coercionKind co
 
     
 
@@ -1685,7 +1710,7 @@ isValue env (Var v)
        -- as well, for let-bound constructors!
 
 isValue env (Lam b e)
-  | isTyCoVar b = case isValue env e of
+  | isTyVar b = case isValue env e of
                  Just _  -> Just LambdaVal
                  Nothing -> Nothing
   | otherwise = Just LambdaVal
@@ -1720,6 +1745,7 @@ samePat (vs1, as1) (vs2, as2)
     same (App f1 a1) (App f2 a2) = same f1 f2 && same a1 a2
 
     same (Type {}) (Type {}) = True    -- Note [Ignore type differences]
+    same (Coercion {}) (Coercion {}) = True
     same (Note _ e1) e2        = same e1 e2    -- Ignore casts and notes
     same (Cast e1 _) e2        = same e1 e2
     same e1 (Note _ e2) = same e1 e2