[project @ 2002-04-22 16:06:35 by simonpj]
[ghc-hetmet.git] / ghc / compiler / simplCore / Simplify.lhs
index 774fa57..5cae204 100644 (file)
@@ -12,7 +12,7 @@ import CmdLineOpts    ( dopt, DynFlag(Opt_D_dump_inlinings),
                          SimplifierSwitch(..)
                        )
 import SimplMonad
-import SimplUtils      ( mkCase, mkLam, newId,
+import SimplUtils      ( mkCase, mkLam, newId, prepareAlts,
                          simplBinder, simplBinders, simplLamBndrs, simplRecBndrs, simplLetBndr,
                          SimplCont(..), DupFlag(..), LetRhsFlag(..), 
                          mkStop, mkBoringStop,  pushContArgs,
@@ -22,10 +22,11 @@ import SimplUtils   ( mkCase, mkLam, newId,
 import Var             ( mustHaveLocalBinding )
 import VarEnv
 import Id              ( Id, idType, idInfo, idArity, isDataConId, 
-                         idUnfolding, setIdUnfolding, isDeadBinder,
+                         setIdUnfolding, isDeadBinder,
                          idNewDemandInfo, setIdInfo,
                          setIdOccInfo, zapLamIdInfo, setOneShotLambda, 
                        )
+import OccName         ( encodeFS )
 import IdInfo          ( OccInfo(..), isLoopBreaker,
                          setArityInfo, 
                          setUnfoldingInfo, 
@@ -35,18 +36,18 @@ import NewDemand    ( isStrictDmd )
 import DataCon         ( dataConNumInstArgs, dataConRepStrictness )
 import CoreSyn
 import PprCore         ( pprParendExpr, pprCoreExpr )
-import CoreUnfold      ( mkOtherCon, mkUnfolding, otherCons, callSiteInline )
+import CoreUnfold      ( mkOtherCon, mkUnfolding, callSiteInline )
 import CoreUtils       ( exprIsDupable, exprIsTrivial, needsCaseBinding,
                          exprIsConApp_maybe, mkPiTypes, findAlt, 
-                         exprType, coreAltsType, exprIsValue, 
-                         exprOkForSpeculation, exprArity, findDefault,
-                         mkCoerce, mkSCC, mkInlineMe, mkAltExpr, applyTypeToArg
+                         exprType, exprIsValue, 
+                         exprOkForSpeculation, exprArity, 
+                         mkCoerce, mkCoerce2, mkSCC, mkInlineMe, mkAltExpr, applyTypeToArg
                        )
 import Rules           ( lookupRule )
 import BasicTypes      ( isMarkedStrict )
 import CostCentre      ( currentCCS )
-import Type            ( isUnLiftedType, seqType, mkFunTy, tyConAppArgs, funArgTy,
-                         funResultTy, splitFunTy_maybe, splitFunTy, eqType
+import Type            ( isUnLiftedType, seqType, tyConAppArgs, funArgTy,
+                         splitFunTy_maybe, splitFunTy, eqType
                        )
 import Subst           ( mkSubst, substTy, substExpr,
                          isInScope, lookupIdSubst, simplIdInfo
@@ -59,6 +60,7 @@ import BasicTypes     ( TopLevelFlag(..), isTopLevel,
 import OrdList
 import Maybe           ( Maybe )
 import Outputable
+import Util             ( notNull )
 \end{code}
 
 
@@ -246,8 +248,15 @@ simplTopBinds env binds
     drop_bs (NonRec _ _) (_ : bs) = bs
     drop_bs (Rec prs)    bs      = drop (length prs) bs
 
-    simpl_bind env (NonRec b r) (b':_) = simplRecOrTopPair env TopLevel b b' r
-    simpl_bind env (Rec pairs)  bs'    = simplRecBind      env TopLevel pairs bs'
+    simpl_bind env bind bs 
+      = getDOptsSmpl                           `thenSmpl` \ dflags ->
+        if dopt Opt_D_dump_inlinings dflags then
+          pprTrace "SimplBind" (ppr (bindersOf bind)) $ simpl_bind1 env bind bs
+       else
+          simpl_bind1 env bind bs
+
+    simpl_bind1 env (NonRec b r) (b':_) = simplRecOrTopPair env TopLevel b b' r
+    simpl_bind1 env (Rec pairs)  bs'    = simplRecBind      env TopLevel pairs bs'
 \end{code}
 
 
@@ -294,16 +303,22 @@ simplNonRecBind env bndr rhs rhs_se cont_ty thing_inside
 
   | isStrictDmd (idNewDemandInfo bndr) || isStrictType (idType bndr)   -- A strict let
   =    -- Don't use simplBinder because that doesn't keep 
-       -- fragile occurrence in the substitution
+       -- fragile occurrence info in the substitution
     simplLetBndr env bndr                                      `thenSmpl` \ (env, bndr') ->
-    simplStrictArg AnRhs env rhs rhs_se (idType bndr') cont_ty $ \ env rhs1 ->
+    let
+       -- simplLetBndr doesn't deal with the IdInfo, so we must
+       -- do so here (c.f. simplLazyBind)
+       bndr''  = bndr' `setIdInfo` simplIdInfo (getSubst env) (idInfo bndr)
+       env1    = modifyInScope env bndr'' bndr''
+    in
+    simplStrictArg AnRhs env1 rhs rhs_se (idType bndr') cont_ty        $ \ env rhs1 ->
 
        -- Now complete the binding and simplify the body
-    completeNonRecX env True {- strict -} bndr bndr' rhs1 thing_inside
+    completeNonRecX env True {- strict -} bndr bndr'' rhs1 thing_inside
 
   | otherwise                                                  -- Normal, lazy case
   =    -- Don't use simplBinder because that doesn't keep 
-       -- fragile occurrence in the substitution
+       -- fragile occurrence info in the substitution
     simplLetBndr env bndr                              `thenSmpl` \ (env, bndr') ->
     simplLazyBind env NotTopLevel NonRecursive
                  bndr bndr' rhs rhs_se                 `thenSmpl` \ (floats, env) ->
@@ -321,6 +336,18 @@ simplNonRecX :: SimplEnv
             -> SimplM FloatsWithExpr
 
 simplNonRecX env bndr new_rhs thing_inside
+  | needsCaseBinding (idType bndr) new_rhs
+       -- Make this test *before* the preInlineUnconditionally
+       -- Consider     case I# (quotInt# x y) of 
+       --                I# v -> let w = J# v in ...
+       -- If we gaily inline (quotInt# x y) for v, we end up building an
+       -- extra thunk:
+       --                let w = J# (quotInt# x y) in ...
+       -- because quotInt# can fail.
+  = simplBinder env bndr       `thenSmpl` \ (env, bndr') ->
+    thing_inside env           `thenSmpl` \ (floats, body) ->
+    returnSmpl (emptyFloats env, Case new_rhs bndr' [(DEFAULT, [], wrapFloats floats body)])
+
   | preInlineUnconditionally env NotTopLevel  bndr
        -- This happens; for example, the case_bndr during case of
        -- known constructor:  case (a,b) of x { (p,q) -> ... }
@@ -338,11 +365,6 @@ simplNonRecX env bndr new_rhs thing_inside
                    bndr bndr' new_rhs thing_inside
 
 completeNonRecX env is_strict old_bndr new_bndr new_rhs thing_inside
-  | needsCaseBinding (idType new_bndr) new_rhs
-  = thing_inside env                   `thenSmpl` \ (floats, body) ->
-    returnSmpl (emptyFloats env, Case new_rhs new_bndr [(DEFAULT, [], wrapFloats floats body)])
-
-  | otherwise
   = mkAtomicArgs is_strict 
                 True {- OK to float unlifted -} 
                 new_rhs                        `thenSmpl` \ (aux_binds, rhs2) ->
@@ -441,13 +463,12 @@ simplLazyBind env top_lvl is_rec bndr bndr' rhs rhs_se
        --
        -- NB: does no harm for non-recursive bindings
     let
-       is_top_level      = isTopLevel top_lvl
-       bndr_ty'          = idType bndr'
-       bndr''            = simplIdInfo (getSubst rhs_se) (idInfo bndr) bndr'
+       bndr''            = bndr' `setIdInfo` simplIdInfo (getSubst env) (idInfo bndr)
        env1              = modifyInScope env bndr'' bndr''
        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 bndr_ty' AnRhs
+       rhs_cont          = mkStop (idType bndr') AnRhs
     in
        -- Simplify the RHS; note the mkStop, which tells 
        -- the simplifier that this is the RHS of a let.
@@ -545,7 +566,7 @@ completeLazyBind :: SimplEnv
 --     (as usual) use the in-scope-env from the floats
 
 completeLazyBind env top_lvl old_bndr new_bndr new_rhs
-  | postInlineUnconditionally env new_bndr loop_breaker new_rhs
+  | postInlineUnconditionally env new_bndr occ_info new_rhs
   =            -- Drop the binding
     tick (PostInlineUnconditionally old_bndr)  `thenSmpl_`
     returnSmpl (emptyFloats env, extendSubst env old_bndr (DoneEx new_rhs))
@@ -788,7 +809,7 @@ simplNote env (Coerce to from) body cont
                -- But it isn't a common case.
          = let 
                (t1,t2) = splitFunTy t1t2
-               new_arg = mkCoerce s1 t1 (substExpr (mkSubst in_scope (getSubstEnv arg_se)) arg)
+               new_arg = mkCoerce2 s1 t1 (substExpr (mkSubst in_scope (getSubstEnv arg_se)) arg)
            in
            ApplyTo dup new_arg (zapSubstEnv env) (addCoerce t2 s2 cont)
                        
@@ -909,8 +930,8 @@ completeCall env var occ_info cont
     let
        arg_infos = [ interestingArg arg | arg <- args, isValArg arg]
 
-       interesting_cont = interestingCallContext (not (null args)) 
-                                                 (not (null arg_infos))
+       interesting_cont = interestingCallContext (notNull args)
+                                                 (notNull arg_infos)
                                                  call_cont
 
        active_inline = activeInline env var occ_info
@@ -1127,7 +1148,7 @@ mkAtomicArgs is_strict ok_float_unlifted rhs
        | otherwise     -- Don't forget to do it recursively
                        -- E.g.  x = a:b:c:[]
        =  mkAtomicArgs is_strict ok_float_unlifted arg `thenSmpl` \ (arg_binds, arg') ->
-          newId SLIT("a") arg_ty                       `thenSmpl` \ arg_id ->
+          newId FSLIT("a") arg_ty                      `thenSmpl` \ arg_id ->
           go fun ((arg_binds `snocOL` (arg_id,arg')) `appOL` binds) 
              (Var arg_id : rev_args) args
        where
@@ -1175,7 +1196,7 @@ rebuild :: SimplEnv -> OutExpr -> SimplCont -> SimplM FloatsWithExpr
 
 rebuild env expr (Stop _ _ _)                = rebuildDone env expr
 rebuild env expr (ArgOf _ _ _ cont_fn)       = cont_fn env expr
-rebuild env expr (CoerceIt to_ty cont)       = rebuild env (mkCoerce to_ty (exprType expr) expr) cont
+rebuild env expr (CoerceIt to_ty cont)       = rebuild env (mkCoerce to_ty expr) cont
 rebuild env expr (InlinePlease cont)         = rebuild env (Note InlineCall expr) cont
 rebuild env expr (Select _ bndr alts se cont) = rebuildCase (setInScope se env) expr bndr alts cont
 rebuild env expr (ApplyTo _ arg se cont)      = rebuildApp  (setInScope se env) expr arg cont
@@ -1218,38 +1239,22 @@ rebuildCase env scrut case_bndr alts cont
   = knownCon env (LitAlt lit) [] case_bndr alts cont
 
   | otherwise
-  =    -- Prepare case alternatives
-       -- Filter out alternatives that can't possibly match
-    let
-        impossible_cons = case scrut of
-                           Var v -> otherCons (idUnfolding v)
-                           other -> []
-       better_alts = case impossible_cons of
-                       []    -> alts
-                       other -> [alt | alt@(con,_,_) <- alts, 
-                                       not (con `elem` impossible_cons)]
-
-       -- "handled_cons" are handled either by the context, 
-       -- or by a branch in this case expression
-       -- Don't add DEFAULT to the handled_cons!!
-       (alts_wo_default, _) = findDefault better_alts
-       handled_cons = impossible_cons ++ [con | (con,_,_) <- alts_wo_default]
-    in
+  = prepareAlts scrut case_bndr alts           `thenSmpl` \ (better_alts, handled_cons) -> 
 
        -- Deal with the case binder, and prepare the continuation;
        -- The new subst_env is in place
-    prepareCaseCont env better_alts cont               `thenSmpl` \ (floats, (dup_cont, nondup_cont)) ->
-    addFloats env floats                               $ \ env ->      
+    prepareCaseCont env better_alts cont       `thenSmpl` \ (floats, (dup_cont, nondup_cont)) ->
+    addFloats env floats                       $ \ env ->      
 
        -- Deal with variable scrutinee
-    simplCaseBinder env scrut case_bndr                `thenSmpl` \ (alt_env, case_bndr', zap_occ_info) ->
+    simplCaseBinder env scrut case_bndr        `thenSmpl` \ (alt_env, case_bndr', zap_occ_info) ->
 
        -- Deal with the case alternatives
     simplAlts alt_env zap_occ_info handled_cons
-             case_bndr' better_alts dup_cont           `thenSmpl` \ alts' ->
+             case_bndr' better_alts dup_cont   `thenSmpl` \ alts' ->
 
        -- Put the case back together
-    mkCase scrut handled_cons case_bndr' alts'         `thenSmpl` \ case_expr ->
+    mkCase scrut case_bndr' alts'              `thenSmpl` \ case_expr ->
 
        -- Notice that rebuildDone returns the in-scope set from env, not alt_env
        -- The case binder *not* scope over the whole returned case-expression
@@ -1285,10 +1290,10 @@ We'll perform the binder-swap for the outer case, giving
     case x of w1 { DEFAULT -> case w1 of w2 { A -> e1; B -> e2 } 
                   ...other cases .... }
 
-But there is no point in doing it for the inner case,
-because w1 can't be inlined anyway.   Furthermore, doing the case-swapping
-involves zapping w2's occurrence info (see paragraphs that follow),
-and that forces us to bind w2 when doing case merging.  So we get
+But there is no point in doing it for the inner case, because w1 can't
+be inlined anyway.  Furthermore, doing the case-swapping involves
+zapping w2's occurrence info (see paragraphs that follow), and that
+forces us to bind w2 when doing case merging.  So we get
 
     case x of w1 { A -> let w2 = w1 in e1
                   B -> let w2 = w1 in e2
@@ -1556,7 +1561,7 @@ mkDupableCont env (ApplyTo _ arg se cont)
     if exprIsDupable arg' then
        returnSmpl (emptyFloats env, (ApplyTo OkToDup arg' (zapSubstEnv se) dup_cont, nondup_cont))
     else
-    newId SLIT("a") (exprType arg')                    `thenSmpl` \ arg_id ->
+    newId FSLIT("a") (exprType arg')                   `thenSmpl` \ arg_id ->
 
     tick (CaseOfCase arg_id)                           `thenSmpl_`
        -- Want to tick here so that we go round again,
@@ -1675,14 +1680,14 @@ mkDupableAlt env case_bndr' cont alt@(con, bndrs, rhs)
        -- (the \v alone is enough to make CPR happy) but I think it's rare
 
     ( if null used_bndrs' 
-       then newId SLIT("w") realWorldStatePrimTy       `thenSmpl` \ rw_id ->
+       then newId FSLIT("w") realWorldStatePrimTy      `thenSmpl` \ rw_id ->
             returnSmpl ([rw_id], [Var realWorldPrimId])
        else 
             returnSmpl (used_bndrs', map varToCoreExpr used_bndrs')
     )                                                  `thenSmpl` \ (final_bndrs', final_args) ->
 
        -- See comment about "$j" name above
-    newId SLIT("$j") (mkPiTypes final_bndrs' rhs_ty')  `thenSmpl` \ join_bndr ->
+    newId (encodeFS SLIT("$j")) (mkPiTypes final_bndrs' rhs_ty')       `thenSmpl` \ join_bndr ->
        -- Notice the funky mkPiTypes.  If the contructor has existentials
        -- it's possible that the join point will be abstracted over
        -- type varaibles as well as term variables.