Improve handling of inline pragmas, esp where type applications are involved
[ghc-hetmet.git] / compiler / simplCore / Simplify.lhs
index 5b68cc5..5d40071 100644 (file)
@@ -8,20 +8,19 @@ module Simplify ( simplTopBinds, simplExpr ) where
 
 #include "HsVersions.h"
 
-import DynFlags        ( dopt, DynFlag(Opt_D_dump_inlinings),
-                         SimplifierSwitch(..)
-                       )
+import DynFlags
 import SimplMonad
 import Type hiding     ( substTy, extendTvSubst )
 import SimplEnv        
 import SimplUtils
 import Id
+import Var
 import IdInfo
 import Coercion
-import TcGadt          ( dataConCanMatch )
-import DataCon         ( dataConTyCon, dataConRepStrictness )
-import TyCon           ( tyConArity, isAlgTyCon, isNewTyCon, tyConDataCons_maybe )
+import FamInstEnv      ( topNormaliseType )
+import DataCon         ( dataConRepStrictness, dataConUnivTyVars )
 import CoreSyn
+import NewDemand       ( isStrictDmd )
 import PprCore         ( pprParendExpr, pprCoreExpr )
 import CoreUnfold      ( mkUnfolding, callSiteInline )
 import CoreUtils
@@ -32,7 +31,6 @@ import TysPrim                ( realWorldStatePrimTy )
 import PrelInfo                ( realWorldPrimId )
 import BasicTypes      ( TopLevelFlag(..), isTopLevel, 
                          RecFlag(..), isNonRuleLoopBreaker )
-import List            ( nub )
 import Maybes          ( orElse )
 import Outputable
 import Util
@@ -208,7 +206,8 @@ simplTopBinds env binds
                -- It's rather as if the top-level binders were imported.
        ; env <- simplRecBndrs env (bindersOfBinds binds)
        ; dflags <- getDOptsSmpl
-       ; let dump_flag = dopt Opt_D_dump_inlinings dflags
+       ; let dump_flag = dopt Opt_D_dump_inlinings dflags || 
+                         dopt Opt_D_dump_rule_firings dflags
        ; env' <- simpl_binds dump_flag env binds
        ; freeTick SimplifierDone
        ; return (getFloats env') }
@@ -216,6 +215,9 @@ simplTopBinds env binds
        -- We need to track the zapped top-level binders, because
        -- they should have their fragile IdInfo zapped (notably occurrence info)
        -- That's why we run down binds and bndrs' simultaneously.
+       --
+       -- The dump-flag emits a trace for each top-level binding, which
+       -- helps to locate the tracing for inlining and rule firing
     simpl_binds :: Bool -> SimplEnv -> [InBind] -> SimplM SimplEnv
     simpl_binds dump env []          = return env
     simpl_binds dump env (bind:binds) = do { env' <- trace dump bind $
@@ -304,46 +306,38 @@ simplLazyBind :: SimplEnv
              -> SimplM SimplEnv
 
 simplLazyBind env top_lvl is_rec bndr bndr1 rhs rhs_se
-  = do { let   rhs_env  = rhs_se `setInScope` env
-               rhs_cont = mkRhsStop (idType bndr1)
+  = do { let   rhs_env     = rhs_se `setInScope` env
+               (tvs, body) = collectTyBinders rhs
+       ; (body_env, tvs') <- simplBinders rhs_env tvs
+               -- See Note [Floating and type abstraction]
+               -- in SimplUtils
 
        -- Simplify the RHS; note the mkRhsStop, which tells 
        -- the simplifier that this is the RHS of a let.
-       ; (rhs_env1, rhs1) <- simplExprF rhs_env rhs rhs_cont
-
-       -- If any of the floats can't be floated, give up now
-       -- (The canFloat predicate says True for empty floats.)
-       ; if (not (canFloat top_lvl is_rec False rhs_env1))
-         then  completeBind env top_lvl bndr bndr1
-                                (wrapFloats rhs_env1 rhs1)
-         else do
+       ; let rhs_cont = mkRhsStop (applyTys (idType bndr1) (mkTyVarTys tvs'))
+       ; (body_env1, body1) <- simplExprF body_env body rhs_cont
+
        -- ANF-ise a constructor or PAP rhs
-       { (rhs_env2, rhs2) <- prepareRhs rhs_env1 rhs1
-       ; (env', rhs3) <- chooseRhsFloats top_lvl is_rec False env rhs_env2 rhs2
-       ; completeBind env' top_lvl bndr bndr1 rhs3 } }
-
-chooseRhsFloats :: TopLevelFlag -> RecFlag -> Bool
-               -> SimplEnv     -- Env for the let
-               -> SimplEnv     -- Env for the RHS, with RHS floats in it
-               -> OutExpr              -- ..and the RHS itself
-               -> SimplM (SimplEnv, OutExpr)   -- New env for let, and RHS
-
-chooseRhsFloats top_lvl is_rec is_strict env rhs_env rhs
-  | not (isEmptyFloats rhs_env)                -- Something to float
-  , canFloat top_lvl is_rec is_strict rhs_env  -- ...that can float
-  , (isTopLevel top_lvl  || exprIsCheap rhs)   -- ...and we want to float      
-  = do { tick LetFloatFromLet  -- Float
-       ; return (addFloats env rhs_env, rhs) } -- Add the floats to the main env
-  | otherwise                  -- Don't float
-  = return (env, wrapFloats rhs_env rhs)       -- Wrap the floats around the RHS
-\end{code}
+       ; (body_env2, body2) <- prepareRhs body_env1 body1
 
+       ; (env', rhs')
+           <-  if not (doFloatFromRhs top_lvl is_rec False body2 body_env2)
+               then                            -- No floating, just wrap up!
+                    do { rhs' <- mkLam tvs' (wrapFloats body_env2 body2)
+                       ; return (env, rhs') }
 
-%************************************************************************
-%*                                                                     *
-\subsection{simplNonRec}
-%*                                                                     *
-%************************************************************************
+               else if null tvs then           -- Simple floating
+                    do { tick LetFloatFromLet
+                       ; return (addFloats env body_env2, body2) }
+
+               else                            -- Do type-abstraction first
+                    do { tick LetFloatFromLet
+                       ; (poly_binds, body3) <- abstractFloats tvs' body_env2 body2
+                       ; rhs' <- mkLam tvs' body3
+                       ; return (extendFloats env poly_binds, rhs') }
+
+       ; completeBind env' top_lvl bndr bndr1 rhs' }
+\end{code}
 
 A specialised variant of simplNonRec used when the RHS is already simplified, 
 notably in knownCon.  It uses case-binding where necessary.
@@ -357,7 +351,7 @@ simplNonRecX :: SimplEnv
 simplNonRecX env bndr new_rhs
   = do { (env, bndr') <- simplBinder env bndr
        ; completeNonRecX env NotTopLevel NonRecursive
-                         (isStrictBndr bndr) bndr bndr' new_rhs }
+                         (isStrictId bndr) bndr bndr' new_rhs }
 
 completeNonRecX :: SimplEnv
                -> TopLevelFlag -> RecFlag -> Bool
@@ -368,7 +362,11 @@ completeNonRecX :: SimplEnv
 
 completeNonRecX env top_lvl is_rec is_strict old_bndr new_bndr new_rhs
   = do         { (env1, rhs1) <- prepareRhs (zapFloats env) new_rhs
-       ; (env2, rhs2) <- chooseRhsFloats top_lvl is_rec is_strict env env1 rhs1
+       ; (env2, rhs2) <- 
+               if doFloatFromRhs top_lvl is_rec is_strict rhs1 env1
+               then do { tick LetFloatFromLet
+                       ; return (addFloats env env1, rhs1) }   -- Add the floats to the main env
+               else return (env, wrapFloats env1 rhs1)         -- Wrap the floats around the RHS
        ; completeBind env2 NotTopLevel old_bndr new_bndr rhs2 }
 \end{code}
 
@@ -397,6 +395,7 @@ completeNonRecX env top_lvl is_rec is_strict old_bndr new_bndr new_rhs
   = thing_inside (extendIdSubst env bndr (DoneEx new_rhs))
 -}
 
+----------------------------------
 prepareRhs takes a putative RHS, checks whether it's a PAP or
 constructor application and, if so, converts it to ANF, so that the 
 resulting thing can be inlined more easily.  Thus
@@ -406,29 +405,46 @@ becomes
        t2 = g b
        x = (t1,t2)
 
+We also want to deal well cases like this
+       v = (f e1 `cast` co) e2
+Here we want to make e1,e2 trivial and get
+       x1 = e1; x2 = e2; v = (f x1 `cast` co) v2
+That's what the 'go' loop in prepareRhs does
+
 \begin{code}
 prepareRhs :: SimplEnv -> OutExpr -> SimplM (SimplEnv, OutExpr)
 -- Adds new floats to the env iff that allows us to return a good RHS
-
-prepareRhs env (Cast rhs co)   -- Note [Float coersions]
+prepareRhs env (Cast rhs co)   -- Note [Float coercions]
   = do { (env', rhs') <- makeTrivial env rhs
        ; return (env', Cast rhs' co) }
 
 prepareRhs env rhs
-  | (Var fun, args) <- collectArgs rhs         -- It's an application
-  , let n_args = valArgCount args      
-  , n_args > 0                                 -- ...but not a trivial one     
-  , isDataConWorkId fun || n_args < idArity fun        -- ...and it's a constructor or PAP
-  = go env (Var fun) args
+  = do { (is_val, env', rhs') <- go 0 env rhs 
+       ; return (env', rhs') }
   where
-    go env fun []          = return (env, fun)
-    go env fun (arg : args) = do { (env', arg') <- makeTrivial env arg
-                                ; go env' (App fun arg') args }
-
-prepareRhs env rhs             -- The default case
-  = return (env, rhs)
+    go n_val_args env (Cast rhs co)
+       = do { (is_val, env', rhs') <- go n_val_args env rhs
+            ; return (is_val, env', Cast rhs' co) }
+    go n_val_args env (App fun (Type ty))
+       = do { (is_val, env', rhs') <- go n_val_args env fun
+            ; return (is_val, env', App rhs' (Type ty)) }
+    go n_val_args env (App fun arg)
+       = do { (is_val, env', fun') <- go (n_val_args+1) env fun
+            ; case is_val of
+               True -> do { (env'', arg') <- makeTrivial env' arg
+                          ; return (True, env'', App fun' arg') }
+               False -> return (False, env, App fun arg) }
+    go n_val_args env (Var fun)
+       = return (is_val, env, Var fun)
+       where
+         is_val = n_val_args > 0       -- There is at least one arg
+                                       -- ...and the fun a constructor or PAP
+                && (isDataConWorkId fun || n_val_args < idArity fun)
+    go n_val_args env other
+       = return (False, env, other)
 \end{code}
 
+
 Note [Float coercions]
 ~~~~~~~~~~~~~~~~~~~~~~
 When we find the binding
@@ -553,7 +569,7 @@ completeBind env top_lvl old_bndr new_bndr new_rhs
     loop_breaker = isNonRuleLoopBreaker occ_info
     old_info     = idInfo old_bndr
     occ_info     = occInfo old_info
-\end{code}    
+\end{code}
 
 
 
@@ -630,12 +646,12 @@ simplExprF env e cont
   = -- pprTrace "simplExprF" (ppr e $$ ppr cont $$ ppr (seTvSubst env) $$ ppr (seIdSubst env) {- $$ ppr (seFloats env) -} ) $
     simplExprF' env e cont
                                     
-simplExprF' env (Var v)              cont = simplVar env v cont
+simplExprF' env (Var v)               cont = simplVar env v cont
 simplExprF' env (Lit lit)      cont = rebuild env (Lit lit) cont
 simplExprF' env (Note n expr)  cont = simplNote env n expr cont
 simplExprF' env (Cast body co) cont = simplCast env body co cont
 simplExprF' env (App fun arg)  cont = simplExprF env fun $
-                                    ApplyTo NoDup arg env cont
+                                     ApplyTo NoDup arg env cont
 
 simplExprF' env expr@(Lam _ _) cont 
   = simplLam env (map zap bndrs) body cont
@@ -733,12 +749,13 @@ simplCast env body co cont
   = do { co' <- simplType env co
        ; simplExprF env body (addCoerce co' cont) }
   where
-       addCoerce co cont 
-         | (s1, k1) <- coercionKind co
-         , s1 `coreEqType` k1 = cont
-       addCoerce co1 (CoerceIt co2 cont)
-         | (s1, k1) <- coercionKind co1
-         , (l1, t1) <- coercionKind co2
+       addCoerce co cont = add_coerce co (coercionKind co) cont
+
+       add_coerce co (s1, k1) cont     -- co :: ty~ty
+         | s1 `coreEqType` k1 = cont   -- is a no-op
+
+       add_coerce co1 (s1, k2) (CoerceIt co2 cont)
+         | (l1, t1) <- coercionKind co2
                 --     coerce T1 S1 (coerce S1 K1 e)
                -- ==>
                --      e,                      if T1=K1
@@ -751,11 +768,20 @@ simplCast env body co cont
          , s1 `coreEqType` t1  = cont           -- The coerces cancel out  
          | otherwise           = CoerceIt (mkTransCoercion co1 co2) cont
     
-       addCoerce co (ApplyTo dup arg arg_se cont)
-         | not (isTypeArg arg)    -- This whole case only works for value args
-                               -- Could upgrade to have equiv thing for type apps too  
-         , Just (s1s2, t1t2) <- splitCoercionKind_maybe co
-         , isFunTy s1s2
+       add_coerce co (s1s2, t1t2) (ApplyTo dup (Type arg_ty) arg_se cont)
+               -- (f `cast` g) ty  --->   (f ty) `cast` (g @ ty)
+               -- This implements the PushT rule from the paper
+        | Just (tyvar,_) <- splitForAllTy_maybe s1s2
+        , not (isCoVar tyvar)
+        = ApplyTo dup (Type ty') (zapSubstEnv env) (addCoerce (mkInstCoercion co ty') cont)
+        where
+          ty' = substTy arg_se arg_ty
+
+       -- ToDo: the PushC rule is not implemented at all
+
+       add_coerce co (s1s2, t1t2) (ApplyTo dup arg arg_se cont)
+         | not (isTypeArg arg)  -- This implements the Push rule from the paper
+         , isFunTy s1s2          -- t1t2 must be a function type, becuase it's applied
                 -- co : s1s2 :=: t1t2
                --      (coerce (T1->T2) (S1->S2) F) E
                -- ===> 
@@ -768,6 +794,8 @@ simplCast env body co cont
                -- with the InExpr in the argument, so we simply substitute
                -- to make it all consistent.  It's a bit messy.
                -- But it isn't a common case.
+               --
+               -- Example of use: Trac #995
          = ApplyTo dup new_arg (zapSubstEnv env) (addCoerce co2 cont)
          where
            -- we split coercion t1->t2 :=: s1->s2 into t1 :=: s1 and 
@@ -777,7 +805,7 @@ simplCast env body co cont
            new_arg    = mkCoerce (mkSymCoercion co1) arg'
           arg'       = substExpr arg_se arg
 
-       addCoerce co cont = CoerceIt co cont
+       add_coerce co _ cont = CoerceIt co cont
 \end{code}
 
 
@@ -838,12 +866,12 @@ simplNonRecE env bndr (rhs, rhs_se) (bndrs, body) cont
   = do { tick (PreInlineUnconditionally bndr)
        ; simplLam (extendIdSubst env bndr (mkContEx rhs_se rhs)) bndrs body cont }
 
-  | isStrictBndr bndr
+  | isStrictId bndr
   = do { simplExprF (rhs_se `setFloats` env) rhs 
                     (StrictBind bndr bndrs body env cont) }
 
   | otherwise
-  = do { (env, bndr') <- simplBinder env bndr
+  = do { (env, bndr') <- simplNonRecBndr env bndr
        ; env <- simplLazyBind env NotTopLevel NonRecursive bndr bndr' rhs rhs_se
        ; simplLam env bndrs body cont }
 \end{code}
@@ -864,10 +892,10 @@ simplNote env (SCC cc) e cont
 
 -- See notes with SimplMonad.inlineMode
 simplNote env InlineMe e cont
-  | contIsRhsOrArg cont                -- Totally boring continuation; see notes above
+  | Just (inside, outside) <- splitInlineCont cont  -- Boring boring continuation; see notes above
   = do {                       -- Don't inline inside an INLINE expression
-         e' <- simplExpr (setMode inlineMode env) e
-       ; rebuild env (mkInlineMe e') cont }
+         e' <- simplExprC (setMode inlineMode env) e inside
+       ; rebuild env (mkInlineMe e') outside }
 
   | otherwise          -- Dissolve the InlineMe note if there's
                -- an interesting context of any kind to combine with
@@ -875,16 +903,8 @@ simplNote env InlineMe e cont
   = simplExprF env e cont
 
 simplNote env (CoreNote s) e cont
-  = do { e' <- simplExpr env e
-       ; rebuild env (Note (CoreNote s) e') cont }
-
-simplNote env note@(TickBox {}) e cont
-  = do { e' <- simplExpr env e
-       ; rebuild env (Note note e') cont }
-
-simplNote env note@(BinaryTickBox {}) e cont
-  = do { e' <- simplExpr env e
-       ; rebuild env (Note note e') cont }
+  = simplExpr env e    `thenSmpl` \ e' ->
+    rebuild env (Note (CoreNote s) e') cont
 \end{code}
 
 
@@ -932,6 +952,8 @@ completeCall env var cont
        -- the wrapper didn't occur for things that have specialisations till a 
        -- later phase, so but now we just try RULES first
        --
+       -- Note [Self-recursive rules]
+       -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~
        -- You might think that we shouldn't apply rules for a loop breaker: 
        -- doing so might give rise to an infinite loop, because a RULE is
        -- rather like an extra equation for the function:
@@ -943,16 +965,16 @@ completeCall env var cont
        -- is recursive, and hence a loop breaker:
        --      foldr k z (build g) = g k z
        -- So it's up to the programmer: rules can cause divergence
+       ; rules <- getRules
        ; let   in_scope   = getInScope env
-               rules      = getRules env
-               maybe_rule = case activeRule env of
+               maybe_rule = case activeRule dflags env of
                                Nothing     -> Nothing  -- No rules apply
                                Just act_fn -> lookupRule act_fn in_scope 
                                                          rules var args 
        ; case maybe_rule of {
            Just (rule, rule_rhs) -> 
                tick (RuleFired (ru_name rule))                 `thenSmpl_`
-               (if dopt Opt_D_dump_inlinings dflags then
+               (if dopt Opt_D_dump_rule_firings dflags then
                   pprTrace "Rule fired" (vcat [
                        text "Rule:" <+> ftext (ru_name rule),
                        text "Before:" <+> ppr var <+> sep (map pprParendExpr args),
@@ -1011,7 +1033,7 @@ rebuildCall env fun fun_ty (has_rules, []) cont
   -- Then, especially in the first of these cases, we'd like to discard
   -- the continuation, leaving just the bottoming expression.  But the
   -- type might not be right, so we may have to add a coerce.
-  | not (contIsTrivial cont)    -- Only do thia if there is a non-trivial
+  | not (contIsTrivial cont)    -- Only do this if there is a non-trivial
   = return (env, mk_coerce fun)  -- contination to discard, else we do it
   where                                 -- again and again!
     cont_ty = contResultType cont
@@ -1088,6 +1110,10 @@ rebuildCase :: SimplEnv
            -> SimplCont
            -> SimplM (SimplEnv, OutExpr)
 
+--------------------------------------------------
+--     1. Eliminate the case if there's a known constructor
+--------------------------------------------------
+
 rebuildCase env scrut case_bndr alts cont
   | Just (con,args) <- exprIsConApp_maybe scrut        
        -- Works when the scrutinee is a variable with a known unfolding
@@ -1098,15 +1124,65 @@ rebuildCase env scrut case_bndr alts cont
                        -- because literals are inlined more vigorously
   = knownCon env scrut (LitAlt lit) [] case_bndr alts cont
 
-  | otherwise
+
+--------------------------------------------------
+--     2. Eliminate the case if scrutinee is evaluated
+--------------------------------------------------
+
+rebuildCase env scrut case_bndr [(con,bndrs,rhs)] cont
+  -- See if we can get rid of the case altogether
+  -- See the extensive notes on case-elimination above
+  -- mkCase made sure that if all the alternatives are equal, 
+  -- then there is now only one (DEFAULT) rhs
+ | all isDeadBinder bndrs      -- bndrs are [InId]
+
+       -- Check that the scrutinee can be let-bound instead of case-bound
+ , exprOkForSpeculation scrut
+               -- OK not to evaluate it
+               -- This includes things like (==# a# b#)::Bool
+               -- so that we simplify 
+               --      case ==# a# b# of { True -> x; False -> x }
+               -- to just
+               --      x
+               -- This particular example shows up in default methods for
+               -- comparision operations (e.g. in (>=) for Int.Int32)
+       || exprIsHNF scrut                      -- It's already evaluated
+       || var_demanded_later scrut             -- It'll be demanded later
+
+--      || not opt_SimplPedanticBottoms)       -- Or we don't care!
+--     We used to allow improving termination by discarding cases, unless -fpedantic-bottoms was on,
+--     but that breaks badly for the dataToTag# primop, which relies on a case to evaluate
+--     its argument:  case x of { y -> dataToTag# y }
+--     Here we must *not* discard the case, because dataToTag# just fetches the tag from
+--     the info pointer.  So we'll be pedantic all the time, and see if that gives any
+--     other problems
+--     Also we don't want to discard 'seq's
+  = do { tick (CaseElim case_bndr)
+       ; env <- simplNonRecX env case_bndr scrut
+       ; simplExprF env rhs cont }
+  where
+       -- The case binder is going to be evaluated later, 
+       -- and the scrutinee is a simple variable
+    var_demanded_later (Var v) = isStrictDmd (idNewDemandInfo case_bndr)
+                                && not (isTickBoxOp v) 
+                                   -- ugly hack; covering this case is what 
+                                   -- exprOkForSpeculation was intended for.
+    var_demanded_later other   = False
+
+
+--------------------------------------------------
+--     3. Catch-all case
+--------------------------------------------------
+
+rebuildCase env scrut case_bndr alts cont
   = do {       -- Prepare the continuation;
                -- The new subst_env is in place
          (env, dup_cont, nodup_cont) <- prepareCaseCont env alts cont
 
        -- Simplify the alternatives
-       ; (case_bndr', alts') <- simplAlts env scrut case_bndr alts dup_cont
+       ; (scrut', case_bndr', alts') <- simplAlts env scrut case_bndr alts dup_cont
        ; let res_ty' = contResultType dup_cont
-       ; case_expr <- mkCase scrut case_bndr' res_ty' alts'
+       ; case_expr <- mkCase scrut' case_bndr' res_ty' alts'
 
        -- Notice that rebuildDone returns the in-scope set from env, not alt_env
        -- The case binder *not* scope over the whole returned case-expression
@@ -1130,18 +1206,10 @@ in action in spectral/cichelli/Prog.hs:
         [(m,n) | m <- [1..max], n <- [1..max]]
 Hence the check for NoCaseOfCase.
 
-Note [Case of cast]
-~~~~~~~~~~~~~~~~~~~
-Consider       case (v `cast` co) of x { I# ->
-               ... (case (v `cast` co) of {...}) ...
-We'd like to eliminate the inner case.  We can get this neatly by 
-arranging that inside the outer case we add the unfolding
-       v |-> x `cast` (sym co)
-to v.  Then we should inline v at the inner case, cancel the casts, and away we go
-       
-Note 2
-~~~~~~
-There is another situation when we don't want to do it.  If we have
+Note [Suppressing the case binder-swap]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+There is another situation when it might make sense to suppress the
+case-expression binde-swap. If we have
 
     case x of w1 { DEFAULT -> case x of w2 { A -> e1; B -> e2 }
                   ...other cases .... }
@@ -1203,31 +1271,183 @@ The point is that we bring into the envt a binding
 after the outer case, and that makes (a,b) alive.  At least we do unless
 the case binder is guaranteed dead.
 
+Note [Case of cast]
+~~~~~~~~~~~~~~~~~~~
+Consider       case (v `cast` co) of x { I# ->
+               ... (case (v `cast` co) of {...}) ...
+We'd like to eliminate the inner case.  We can get this neatly by 
+arranging that inside the outer case we add the unfolding
+       v |-> x `cast` (sym co)
+to v.  Then we should inline v at the inner case, cancel the casts, and away we go
+       
+Note [Improving seq]
+~~~~~~~~~~~~~~~~~~~
+Consider
+       type family F :: * -> *
+       type instance F Int = Int
+
+       ... case e of x { DEFAULT -> rhs } ...
+
+where x::F Int.  Then we'd like to rewrite (F Int) to Int, getting
+
+       case e `cast` co of x'::Int
+          I# x# -> let x = x' `cast` sym co 
+                   in rhs
+
+so that 'rhs' can take advantage of hte form of x'.  Notice that Note
+[Case of cast] may then apply to the result.
+
+This showed up in Roman's experiments.  Example:
+  foo :: F Int -> Int -> Int
+  foo t n = t `seq` bar n
+     where
+       bar 0 = 0
+       bar n = bar (n - case t of TI i -> i)
+Here we'd like to avoid repeated evaluating t inside the loop, by 
+taking advantage of the `seq`.
+
+At one point I did transformation in LiberateCase, but it's more robust here.
+(Otherwise, there's a danger that we'll simply drop the 'seq' altogether, before
+LiberateCase gets to see it.)
+
+Note [Case elimination]
+~~~~~~~~~~~~~~~~~~~~~~~
+The case-elimination transformation discards redundant case expressions.
+Start with a simple situation:
+
+       case x# of      ===>   e[x#/y#]
+         y# -> e
+
+(when x#, y# are of primitive type, of course).  We can't (in general)
+do this for algebraic cases, because we might turn bottom into
+non-bottom!
+
+The code in SimplUtils.prepareAlts has the effect of generalise this
+idea to look for a case where we're scrutinising a variable, and we
+know that only the default case can match.  For example:
+
+       case x of
+         0#      -> ...
+         DEFAULT -> ...(case x of
+                        0#      -> ...
+                        DEFAULT -> ...) ...
+
+Here the inner case is first trimmed to have only one alternative, the
+DEFAULT, after which it's an instance of the previous case.  This
+really only shows up in eliminating error-checking code.
+
+We also make sure that we deal with this very common case:
+
+       case e of 
+         x -> ...x...
+
+Here we are using the case as a strict let; if x is used only once
+then we want to inline it.  We have to be careful that this doesn't 
+make the program terminate when it would have diverged before, so we
+check that 
+       - e is already evaluated (it may so if e is a variable)
+       - x is used strictly, or
+
+Lastly, the code in SimplUtils.mkCase combines identical RHSs.  So
+
+       case e of       ===> case e of DEFAULT -> r
+          True  -> r
+          False -> r
+
+Now again the case may be elminated by the CaseElim transformation.
+
+
+Further notes about case elimination
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Consider:      test :: Integer -> IO ()
+               test = print
+
+Turns out that this compiles to:
+    Print.test
+      = \ eta :: Integer
+         eta1 :: State# RealWorld ->
+         case PrelNum.< eta PrelNum.zeroInteger of wild { __DEFAULT ->
+         case hPutStr stdout
+                (PrelNum.jtos eta ($w[] @ Char))
+                eta1
+         of wild1 { (# new_s, a4 #) -> PrelIO.lvl23 new_s  }}
+
+Notice the strange '<' which has no effect at all. This is a funny one.  
+It started like this:
+
+f x y = if x < 0 then jtos x
+          else if y==0 then "" else jtos x
+
+At a particular call site we have (f v 1).  So we inline to get
+
+       if v < 0 then jtos x 
+       else if 1==0 then "" else jtos x
+
+Now simplify the 1==0 conditional:
+
+       if v<0 then jtos v else jtos v
+
+Now common-up the two branches of the case:
+
+       case (v<0) of DEFAULT -> jtos v
+
+Why don't we drop the case?  Because it's strict in v.  It's technically
+wrong to drop even unnecessary evaluations, and in practice they
+may be a result of 'seq' so we *definitely* don't want to drop those.
+I don't really know how to improve this situation.
+
+
 \begin{code}
-simplCaseBinder :: SimplEnv -> OutExpr -> InId -> SimplM (SimplEnv, OutId)
-simplCaseBinder env scrut case_bndr
-  | switchIsOn (getSwitchChecker env) NoCaseOfCase
-       -- See Note [no-case-of-case]
-  = do { (env, case_bndr') <- simplBinder env case_bndr
-       ; return (env, case_bndr') }
-
-simplCaseBinder env (Var v) case_bndr
--- Failed try [see Note 2 above]
---     not (isEvaldUnfolding (idUnfolding v))
-  = do { (env, case_bndr') <- simplBinder env (zapOccInfo case_bndr)
-       ; return (modifyInScope env v case_bndr', case_bndr') }
-       -- We could extend the substitution instead, but it would be
-       -- a hack because then the substitution wouldn't be idempotent
-       -- any more (v is an OutId).  And this does just as well.
-           
-simplCaseBinder env (Cast (Var v) co) case_bndr                -- Note [Case of cast]
-  = do { (env, case_bndr') <- simplBinder env (zapOccInfo case_bndr)
-       ; let rhs = Cast (Var case_bndr') (mkSymCoercion co)
-       ; return (addBinderUnfolding env v rhs, case_bndr') }
-
-simplCaseBinder env other_scrut case_bndr 
-  = do { (env, case_bndr') <- simplBinder env case_bndr
-       ; return (env, case_bndr') }
+simplCaseBinder :: SimplEnv -> OutExpr -> OutId -> [InAlt]
+               -> SimplM (SimplEnv, OutExpr, OutId)
+simplCaseBinder env scrut case_bndr alts
+  = do { (env1, case_bndr1) <- simplBinder env case_bndr
+
+       ; fam_envs <- getFamEnvs
+       ; (env2, scrut2, case_bndr2) <- improve_seq fam_envs env1 scrut 
+                                               case_bndr case_bndr1 alts
+                       -- Note [Improving seq]
+
+       ; let (env3, case_bndr3) = improve_case_bndr env2 scrut2 case_bndr2
+                       -- Note [Case of cast]
+
+       ; return (env3, scrut2, case_bndr3) }
+  where
+
+    improve_seq fam_envs env1 scrut case_bndr case_bndr1 [(DEFAULT,_,_)] 
+       | Just (co, ty2) <- topNormaliseType fam_envs (idType case_bndr1)
+       =  do { case_bndr2 <- newId FSLIT("nt") ty2
+             ; let rhs  = DoneEx (Var case_bndr2 `Cast` mkSymCoercion co)
+                   env2 = extendIdSubst env1 case_bndr rhs
+             ; return (env2, scrut `Cast` co, case_bndr2) }
+
+    improve_seq fam_envs env1 scrut case_bndr case_bndr1 alts
+       = return (env1, scrut, case_bndr1)
+
+
+    improve_case_bndr env scrut case_bndr
+       | switchIsOn (getSwitchChecker env) NoCaseOfCase
+               -- See Note [no-case-of-case]
+       = (env, case_bndr)
+
+       | otherwise     -- Failed try [see Note 2 above]
+                       --     not (isEvaldUnfolding (idUnfolding v))
+       = case scrut of
+           Var v -> (modifyInScope env1 v case_bndr', case_bndr')
+               -- Note about using modifyInScope for v here
+               -- We could extend the substitution instead, but it would be
+               -- a hack because then the substitution wouldn't be idempotent
+               -- any more (v is an OutId).  And this does just as well.
+
+           Cast (Var v) co -> (addBinderUnfolding env1 v rhs, case_bndr')
+                           where
+                               rhs = Cast (Var case_bndr') (mkSymCoercion co)
+
+           other -> (env, case_bndr)
+       where
+         case_bndr' = zapOccInfo case_bndr
+         env1       = modifyInScope env case_bndr case_bndr'
+
 
 zapOccInfo :: InId -> InId     -- See Note [zapOccInfo]
 zapOccInfo b = b `setIdOccInfo` NoOccInfo
@@ -1279,134 +1499,57 @@ simplAlts :: SimplEnv
          -> OutExpr
          -> InId                       -- Case binder
          -> [InAlt] -> SimplCont
-         -> SimplM (OutId, [OutAlt])   -- Includes the continuation
+         -> SimplM (OutExpr, OutId, [OutAlt])  -- Includes the continuation
 -- Like simplExpr, this just returns the simplified alternatives;
 -- it not return an environment
 
 simplAlts env scrut case_bndr alts cont'
   = -- pprTrace "simplAlts" (ppr alts $$ ppr (seIdSubst env)) $
     do { let alt_env = zapFloats env
-       ; (alt_env, case_bndr') <- simplCaseBinder alt_env scrut case_bndr
-
-       ; default_alts <- prepareDefault alt_env case_bndr' imposs_deflt_cons cont' maybe_deflt
-
-       ; let inst_tys = tyConAppArgs (idType case_bndr')
-             trimmed_alts = filter (is_possible inst_tys) alts_wo_default
-             in_alts      = mergeAlts default_alts trimmed_alts
-               -- We need the mergeAlts in case the new default_alt 
-               -- has turned into a constructor alternative.
+       ; (alt_env, scrut', case_bndr') <- simplCaseBinder alt_env scrut case_bndr alts
 
-       ; alts' <- mapM (simplAlt alt_env imposs_cons case_bndr' cont') in_alts
-       ; return (case_bndr', alts') }
-  where
-    (alts_wo_default, maybe_deflt) = findDefault alts
-    imposs_cons = case scrut of
-                   Var v -> otherCons (idUnfolding v)
-                   other -> []
-
-       -- "imposs_deflt_cons" are handled either by the context, 
-       -- OR by a branch in this case expression. (Don't include DEFAULT!!)
-    imposs_deflt_cons = nub (imposs_cons ++ [con | (con,_,_) <- alts_wo_default])
+       ; (imposs_deflt_cons, in_alts) <- prepareAlts scrut case_bndr' alts
 
-    is_possible :: [Type] -> CoreAlt -> Bool
-    is_possible tys (con, _, _) | con `elem` imposs_cons = False
-    is_possible tys (DataAlt con, _, _) = dataConCanMatch tys con
-    is_possible tys alt                        = True
-
-------------------------------------
-prepareDefault :: SimplEnv
-              -> OutId         -- Case binder; need just for its type. Note that as an
-                               --   OutId, it has maximum information; this is important.
-                               --   Test simpl013 is an example
-            -> [AltCon]        -- These cons can't happen when matching the default
-            -> SimplCont
-            -> Maybe InExpr
-            -> SimplM [InAlt]  -- One branch or none; still unsimplified
-                               -- We use a list because it's what mergeAlts expects
-
-prepareDefault env case_bndr' imposs_cons cont Nothing
-  = return []  -- No default branch
-
-prepareDefault env case_bndr' imposs_cons cont (Just rhs)
-  |    -- This branch handles the case where we are 
-       -- scrutinisng an algebraic data type
-    Just (tycon, inst_tys) <- splitTyConApp_maybe (idType case_bndr'),
-    isAlgTyCon tycon,          -- It's a data type, tuple, or unboxed tuples.  
-    not (isNewTyCon tycon),    -- We can have a newtype, if we are just doing an eval:
-                               --      case x of { DEFAULT -> e }
-                               -- and we don't want to fill in a default for them!
-    Just all_cons <- tyConDataCons_maybe tycon,
-    not (null all_cons),       -- This is a tricky corner case.  If the data type has no constructors,
-                               -- which GHC allows, then the case expression will have at most a default
-                               -- alternative.  We don't want to eliminate that alternative, because the
-                               -- invariant is that there's always one alternative.  It's more convenient
-                               -- to leave     
-                               --      case x of { DEFAULT -> e }     
-                               -- as it is, rather than transform it to
-                               --      error "case cant match"
-                               -- which would be quite legitmate.  But it's a really obscure corner, and
-                               -- not worth wasting code on.
-
-    let imposs_data_cons = [con | DataAlt con <- imposs_cons]  -- We now know it's a data type 
-       is_possible con  = not (con `elem` imposs_data_cons)
-                          && dataConCanMatch inst_tys con
-  = case filter is_possible all_cons of
-       []    -> return []      -- Eliminate the default alternative
-                               -- altogether if it can't match
-
-       [con] ->        -- It matches exactly one constructor, so fill it in
-                do { tick (FillInCaseDefault case_bndr')
-                    ; us <- getUniquesSmpl
-                    ; let (ex_tvs, co_tvs, arg_ids) =
-                              dataConRepInstPat us con inst_tys
-                    ; return [(DataAlt con, ex_tvs ++ co_tvs ++ arg_ids, rhs)] }
-
-       two_or_more -> return [(DEFAULT, [], rhs)]
-
-  | otherwise 
-  = return [(DEFAULT, [], rhs)]
+       ; alts' <- mapM (simplAlt alt_env imposs_deflt_cons case_bndr' cont') in_alts
+       ; return (scrut', case_bndr', alts') }
 
 ------------------------------------
 simplAlt :: SimplEnv
         -> [AltCon]    -- These constructors can't be present when
-                       -- matching this alternative
+                       -- matching the DEFAULT alternative
         -> OutId       -- The case binder
         -> SimplCont
         -> InAlt
-        -> SimplM (OutAlt)
-
--- Simplify an alternative, returning the type refinement for the 
--- alternative, if the alternative does any refinement at all
+        -> SimplM OutAlt
 
-simplAlt env handled_cons case_bndr' cont' (DEFAULT, bndrs, rhs)
+simplAlt env imposs_deflt_cons case_bndr' cont' (DEFAULT, bndrs, rhs)
   = ASSERT( null bndrs )
-    do { let env' = addBinderOtherCon env case_bndr' handled_cons
+    do { let env' = addBinderOtherCon env case_bndr' imposs_deflt_cons
                -- Record the constructors that the case-binder *can't* be.
        ; rhs' <- simplExprC env' rhs cont'
        ; return (DEFAULT, [], rhs') }
 
-simplAlt env handled_cons case_bndr' cont' (LitAlt lit, bndrs, rhs)
+simplAlt env imposs_deflt_cons case_bndr' cont' (LitAlt lit, bndrs, rhs)
   = ASSERT( null bndrs )
     do { let env' = addBinderUnfolding env case_bndr' (Lit lit)
        ; rhs' <- simplExprC env' rhs cont'
        ; return (LitAlt lit, [], rhs') }
 
-simplAlt env handled_cons case_bndr' cont' (DataAlt con, vs, rhs)
+simplAlt env imposs_deflt_cons case_bndr' cont' (DataAlt con, vs, rhs)
   = do {       -- Deal with the pattern-bound variables
-               -- Mark the ones that are in ! positions in the data constructor
-               -- as certainly-evaluated.
-               -- NB: it happens that simplBinders does *not* erase the OtherCon
-               --     form of unfolding, so it's ok to add this info before 
-               --     doing simplBinders
          (env, vs') <- simplBinders env (add_evals con vs)
 
+               -- Mark the ones that are in ! positions in the
+               -- data constructor as certainly-evaluated.
+       ; let vs'' = add_evals con vs'
+
                -- Bind the case-binder to (con args)
        ; let inst_tys' = tyConAppArgs (idType case_bndr')
-             con_args  = map Type inst_tys' ++ varsToCoreExprs vs' 
+             con_args  = map Type inst_tys' ++ varsToCoreExprs vs'' 
              env'      = addBinderUnfolding env case_bndr' (mkConApp con con_args)
 
        ; rhs' <- simplExprC env' rhs cont'
-       ; return (DataAlt con, vs', rhs') }
+       ; return (DataAlt con, vs'', rhs') }
   where
        -- add_evals records the evaluated-ness of the bound variables of
        -- a case pattern.  This is *important*.  Consider
@@ -1491,8 +1634,8 @@ knownAlt env scrut args bndr (LitAlt lit, bs, rhs) cont
        ; simplExprF env rhs cont }
 
 knownAlt env scrut args bndr (DataAlt dc, bs, rhs) cont
-  = do { let dead_bndr  = isDeadBinder bndr
-             n_drop_tys = tyConArity (dataConTyCon dc)
+  = do { let dead_bndr  = isDeadBinder bndr    -- bndr is an InId
+             n_drop_tys = length (dataConUnivTyVars dc)
        ; env <- bind_args env dead_bndr bs (drop n_drop_tys args)
        ; let
                -- It's useful to bind bndr to scrut, rather than to a fresh
@@ -1590,7 +1733,7 @@ mkDupableCont env cont@(Select _ case_bndr [(_,bs,rhs)] se case_cont)
 --  See Note [Single-alternative case]
 --  | not (exprIsDupable rhs && contIsDupable case_cont)
 --  | not (isDeadBinder case_bndr)
-  | all isDeadBinder bs
+  | all isDeadBinder bs                -- InIds
   = return (env, mkBoringStop scrut_ty, cont)
   where
     scrut_ty = substTy se (idType case_bndr)
@@ -1613,8 +1756,8 @@ mkDupableCont env (Select _ case_bndr alts se cont)
                -- NB: simplBinder does not zap deadness occ-info, so
                -- a dead case_bndr' will still advertise its deadness
                -- This is really important because in
-               --      case e of b { (# a,b #) -> ... }
-               -- b is always dead, and indeed we are not allowed to bind b to (# a,b #),
+               --      case e of b { (# p,q #) -> ... }
+               -- b is always dead, and indeed we are not allowed to bind b to (# p,q #),
                -- which might happen if e was an explicit unboxed pair and b wasn't marked dead.
                -- In the new alts we build, we have the new case binder, so it must retain
                -- its deadness.