[project @ 2006-01-06 16:30:17 by simonmar]
[ghc-hetmet.git] / ghc / compiler / simplCore / Simplify.lhs
index 3ce54cf..17a7969 100644 (file)
@@ -24,11 +24,10 @@ import SimplUtils   ( mkCase, mkLam, prepareAlts,
 import Id              ( Id, idType, idInfo, idArity, isDataConWorkId, 
                          setIdUnfolding, isDeadBinder,
                          idNewDemandInfo, setIdInfo, 
-                         setIdOccInfo, zapLamIdInfo, setOneShotLambda, 
+                         setIdOccInfo, zapLamIdInfo, setOneShotLambda
                        )
 import MkId            ( eRROR_ID )
 import Literal         ( mkStringLit )
-import OccName         ( encodeFS )
 import IdInfo          ( OccInfo(..), isLoopBreaker,
                          setArityInfo, zapDemandInfo,
                          setUnfoldingInfo, 
@@ -40,10 +39,10 @@ import DataCon              ( dataConTyCon, dataConRepStrictness, isVanillaDataCon )
 import TyCon           ( tyConArity )
 import CoreSyn
 import PprCore         ( pprParendExpr, pprCoreExpr )
-import CoreUnfold      ( mkOtherCon, mkUnfolding, evaldUnfolding, callSiteInline )
+import CoreUnfold      ( mkUnfolding, callSiteInline )
 import CoreUtils       ( exprIsDupable, exprIsTrivial, needsCaseBinding,
                          exprIsConApp_maybe, mkPiTypes, findAlt, 
-                         exprType, exprIsValue, 
+                         exprType, exprIsHNF, 
                          exprOkForSpeculation, exprArity, 
                          mkCoerce, mkCoerce2, mkSCC, mkInlineMe, applyTypeToArg
                        )
@@ -53,14 +52,14 @@ import CostCentre   ( currentCCS )
 import Type            ( TvSubstEnv, isUnLiftedType, seqType, tyConAppArgs, funArgTy,
                          splitFunTy_maybe, splitFunTy, coreEqType 
                        )
-import VarEnv          ( elemVarEnv )
+import VarEnv          ( elemVarEnv, emptyVarEnv )
 import TysPrim         ( realWorldStatePrimTy )
 import PrelInfo                ( realWorldPrimId )
 import BasicTypes      ( TopLevelFlag(..), isTopLevel, 
                          RecFlag(..), isNonRec
                        )
+import StaticFlags     ( opt_PprStyle_Debug )
 import OrdList
-import Maybe           ( Maybe )
 import Maybes          ( orElse )
 import Outputable
 import Util             ( notNull )
@@ -524,24 +523,24 @@ simplLazyBind env top_lvl is_rec bndr bndr1 rhs rhs_se
     if isEmptyFloats floats && isNilOL aux_binds then  -- Shortcut a common case
        completeLazyBind env1 top_lvl bndr bndr2 rhs2
 
-    else if is_top_level || exprIsTrivial rhs2 || exprIsValue rhs2 then
+    else if is_top_level || exprIsTrivial rhs2 || exprIsHNF rhs2 then
        --      WARNING: long dodgy argument coming up
        --      WANTED: a better way to do this
        --              
-       -- We can't use "exprIsCheap" instead of exprIsValue, 
+       -- We can't use "exprIsCheap" instead of exprIsHNF, 
        -- because that causes a strictness bug.
        --         x = let y* = E in case (scc y) of { T -> F; F -> T}
        -- The case expression is 'cheap', but it's wrong to transform to
        --         y* = E; x = case (scc y) of {...}
        -- Either we must be careful not to float demanded non-values, or
-       -- we must use exprIsValue for the test, which ensures that the
-       -- thing is non-strict.  So exprIsValue => bindings are non-strict
+       -- we must use exprIsHNF for the test, which ensures that the
+       -- thing is non-strict.  So exprIsHNF => bindings are non-strict
        -- I think.  The WARN below tests for this.
        --
        -- We use exprIsTrivial here because we want to reveal lone variables.  
        -- E.g.  let { x = letrec { y = E } in y } in ...
        -- Here we definitely want to float the y=E defn. 
-       -- exprIsValue definitely isn't right for that.
+       -- exprIsHNF definitely isn't right for that.
        --
        -- Again, the floated binding can't be strict; if it's recursive it'll
        -- be non-strict; if it's non-recursive it'd be inlined.
@@ -615,7 +614,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 occ_info new_rhs
+  | postInlineUnconditionally env top_lvl new_bndr occ_info new_rhs unfolding
   =            -- Drop the binding
     tick (PostInlineUnconditionally old_bndr)  `thenSmpl_`
     returnSmpl (emptyFloats env, extendIdSubst env old_bndr (DoneEx new_rhs))
@@ -844,6 +843,11 @@ mkLamBndrZapper fun n_args
 \begin{code}
 simplNote env (Coerce to from) body cont
   = let
+       addCoerce s1 k1 cont    -- Drop redundant coerces.  This can happen if a polymoprhic
+                               -- (coerce a b e) is instantiated with a=ty1 b=ty2 and the
+                               -- two are the same. This happens a lot in Happy-generated parsers
+         | s1 `coreEqType` k1 = cont
+
        addCoerce s1 k1 (CoerceIt t1 cont)
                --      coerce T1 S1 (coerce S1 K1 e)
                -- ==>
@@ -854,9 +858,9 @@ simplNote env (Coerce to from) body cont
                -- we may find  (coerce T (coerce S (\x.e))) y
                -- and we'd like it to simplify to e[y/x] in one round 
                -- of simplification
-         | t1 `coreEqType` k1  = cont          -- The coerces cancel out
-         | otherwise       = CoerceIt t1 cont  -- They don't cancel, but 
-                                               -- the inner one is redundant
+         | t1 `coreEqType` k1  = cont                  -- The coerces cancel out
+         | otherwise           = CoerceIt t1 cont      -- They don't cancel, but 
+                                                       -- the inner one is redundant
 
        addCoerce t1t2 s1s2 (ApplyTo dup arg arg_se cont)
          | not (isTypeArg arg),        -- This whole case only works for value args
@@ -1321,9 +1325,10 @@ rebuildCase env scrut case_bndr alts cont
   = knownCon env (LitAlt lit) [] case_bndr alts cont
 
   | otherwise
-  = prepareAlts scrut case_bndr alts           `thenSmpl` \ (better_alts, handled_cons) -> 
+  =    -- Prepare the alternatives.
+    prepareAlts scrut case_bndr alts           `thenSmpl` \ (better_alts, handled_cons) -> 
        
-       -- Deal with the case binder, and prepare the continuation;
+       -- 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 ->      
@@ -1340,7 +1345,7 @@ rebuildCase env scrut case_bndr alts cont
        res_ty' = contResultType dup_cont
     in
 
-       -- Deal with variable scrutinee
+       -- Deal with case binder
     simplCaseBinder env scrut case_bndr        `thenSmpl` \ (alt_env, case_bndr') ->
 
        -- Deal with the case alternatives
@@ -1467,20 +1472,22 @@ simplAlts :: SimplEnv
          -> SimplM [OutAlt]            -- Includes the continuation
 
 simplAlts env handled_cons case_bndr' alts cont'
-  = mapSmpl simpl_alt alts
+  = do { mb_alts <- mapSmpl simpl_alt alts
+       ; return [alt' | Just (_, alt') <- mb_alts] }
+       -- Filter out the alternatives that are inaccessible
   where
-    simpl_alt alt = simplAlt env handled_cons case_bndr' alt cont'     `thenSmpl` \ (_, alt') ->
-                   returnSmpl alt'
+    simpl_alt alt = simplAlt env handled_cons case_bndr' alt cont'
 
 simplAlt :: SimplEnv -> [AltCon] -> OutId -> InAlt -> SimplCont
-        -> SimplM (Maybe TvSubstEnv, OutAlt)
+        -> SimplM (Maybe (TvSubstEnv, OutAlt))
 -- Simplify an alternative, returning the type refinement for the 
 -- alternative, if the alternative does any refinement at all
+-- Nothing => the alternative is inaccessible
 
 simplAlt env handled_cons case_bndr' (DEFAULT, bndrs, rhs) cont'
   = ASSERT( null bndrs )
     simplExprC env' rhs cont'  `thenSmpl` \ rhs' ->
-    returnSmpl (Nothing, (DEFAULT, [], rhs'))
+    returnSmpl (Just (emptyVarEnv, (DEFAULT, [], rhs')))
   where
     env' = mk_rhs_env env case_bndr' (mkOtherCon handled_cons)
        -- Record the constructors that the case-binder *can't* be.
@@ -1488,7 +1495,7 @@ simplAlt env handled_cons case_bndr' (DEFAULT, bndrs, rhs) cont'
 simplAlt env handled_cons case_bndr' (LitAlt lit, bndrs, rhs) cont'
   = ASSERT( null bndrs )
     simplExprC env' rhs cont'  `thenSmpl` \ rhs' ->
-    returnSmpl (Nothing, (LitAlt lit, [], rhs'))
+    returnSmpl (Just (emptyVarEnv, (LitAlt lit, [], rhs')))
   where
     env' = mk_rhs_env env case_bndr' (mkUnfolding False (Lit lit))
 
@@ -1509,7 +1516,7 @@ simplAlt env handled_cons case_bndr' (DataAlt con, vs, rhs) cont'
        env'      = mk_rhs_env env case_bndr' unf
     in
     simplExprC env' rhs cont'  `thenSmpl` \ rhs' ->
-    returnSmpl (Nothing, (DataAlt con, vs', rhs'))
+    returnSmpl (Just (emptyVarEnv, (DataAlt con, vs', rhs')))
 
   | otherwise  -- GADT case
   = let
@@ -1517,14 +1524,18 @@ simplAlt env handled_cons case_bndr' (DataAlt con, vs, rhs) cont'
     in
     simplBinders env tvs                       `thenSmpl` \ (env1, tvs') ->
     case coreRefineTys (getInScope env1) con tvs' (idType case_bndr') of {
-       Nothing         -- Dead code; for now, I'm just going to put in an
-                       -- error case so I can see them
+       Nothing         -- Inaccessible
+           | opt_PprStyle_Debug        -- Hack: if debugging is on, generate an error case 
+                                       --       so we can see it
            ->  let rhs' = mkApps (Var eRROR_ID) 
                                [Type (substTy env (exprType rhs)),
                                 Lit (mkStringLit "Impossible alternative (GADT)")]
                in 
                simplBinders env1 ids           `thenSmpl` \ (env2, ids') -> 
-               returnSmpl (Nothing, (DataAlt con, tvs' ++ ids', rhs')) ;
+               returnSmpl (Just (emptyVarEnv, (DataAlt con, tvs' ++ ids', rhs'))) 
+
+           | otherwise -- Filter out the inaccessible branch
+           -> return Nothing ; 
 
        Just refine@(tv_subst_env, _) ->        -- The normal case
 
@@ -1543,7 +1554,7 @@ simplAlt env handled_cons case_bndr' (DataAlt con, vs, rhs) cont'
        vs'        = tvs' ++ ids'
     in
     simplExprC env_w_unf rhs cont'     `thenSmpl` \ rhs' ->
-    returnSmpl (Just tv_subst_env, (DataAlt con, vs', rhs')) }
+    returnSmpl (Just (tv_subst_env, (DataAlt con, vs', rhs'))) }
 
   where
        -- add_evals records the evaluated-ness of the bound variables of
@@ -1740,7 +1751,6 @@ mkDupableCont env (ApplyTo _ arg se cont)
        -- This has been this way for a long time, so I'll leave it,
        -- but I can't convince myself that it's right.
 
--- gaw 2004
 mkDupableCont env (Select _ case_bndr alts se cont)
   =    -- e.g.         (case [...hole...] of { pi -> ei })
        --      ===>
@@ -1779,17 +1789,24 @@ mkDupableAlts env case_bndr' alts dupable_cont
   where
     go env [] = returnSmpl (emptyFloats env, [])
     go env (alt:alts)
-       = mkDupableAlt env case_bndr' dupable_cont alt  `thenSmpl` \ (floats1, alt') ->
-         addFloats env floats1                         $ \ env ->
-         go env alts                                   `thenSmpl` \ (floats2, alts') ->
-         returnSmpl (floats2, alt' : alts')
+       = do { (floats1, mb_alt') <- mkDupableAlt env case_bndr' dupable_cont alt
+            ; addFloats env floats1    $ \ env -> do
+            { (floats2, alts') <- go env alts
+            ; returnSmpl (floats2, case mb_alt' of
+                                       Just alt' -> alt' : alts'
+                                       Nothing   -> alts'
+                         )}}
                                        
 mkDupableAlt env case_bndr' cont alt
-  = simplAlt env [] case_bndr' alt cont                `thenSmpl` \ (mb_reft, (con, bndrs', rhs')) ->
+  = simplAlt env [] case_bndr' alt cont                `thenSmpl` \ mb_stuff ->
+    case mb_stuff of {
+       Nothing -> returnSmpl (emptyFloats env, Nothing) ;
+
+       Just (reft, (con, bndrs', rhs')) ->
        -- Safe to say that there are no handled-cons for the DEFAULT case
 
     if exprIsDupable rhs' then
-       returnSmpl (emptyFloats env, (con, bndrs', rhs'))
+       returnSmpl (emptyFloats env, Just (con, bndrs', rhs'))
        -- It is worth checking for a small RHS because otherwise we
        -- get extra let bindings that may cause an extra iteration of the simplifier to
        -- inline back in place.  Quite often the rhs is just a variable or constructor.
@@ -1811,13 +1828,11 @@ mkDupableAlt env case_bndr' cont alt
        rhs_ty'     = exprType rhs'
         used_bndrs' = filter abstract_over (case_bndr' : bndrs')
        abstract_over bndr
-         | isTyVar bndr = not (mb_reft `refines` bndr)
+         | isTyVar bndr = not (bndr `elemVarEnv` reft)
                -- Don't abstract over tyvar binders which are refined away
+               -- See Note [Refinement] below
          | otherwise    = not (isDeadBinder bndr)
                -- The deadness info on the new Ids is preserved by simplBinders
-       refines Nothing         bndr = False
-       refines (Just tv_subst) bndr = bndr `elemVarEnv` tv_subst       
-               -- See Note [Refinement] below
     in
        -- If we try to lift a primitive-typed something out
        -- for let-binding-purposes, we will *caseify* it (!),
@@ -1859,7 +1874,7 @@ mkDupableAlt env case_bndr' cont alt
     )                                                  `thenSmpl` \ (final_bndrs', final_args) ->
 
        -- See comment about "$j" name above
-    newId (encodeFS FSLIT("$j")) (mkPiTypes final_bndrs' rhs_ty')      `thenSmpl` \ join_bndr ->
+    newId FSLIT("$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.
@@ -1885,7 +1900,7 @@ mkDupableAlt env case_bndr' cont alt
        join_rhs  = mkLams really_final_bndrs rhs'
        join_call = mkApps (Var join_bndr) final_args
     in
-    returnSmpl (unitFloat env join_bndr join_rhs, (con, bndrs', join_call))
+    returnSmpl (unitFloat env join_bndr join_rhs, Just (con, bndrs', join_call)) }
 \end{code}
 
 Note [Refinement]