Add {-# OPTIONS_GHC -w #-} and some blurb to all compiler modules
[ghc-hetmet.git] / compiler / simplCore / Simplify.lhs
index 7464266..79b305d 100644 (file)
@@ -4,6 +4,13 @@
 \section[Simplify]{The main module of the simplifier}
 
 \begin{code}
+{-# OPTIONS_GHC -w #-}
+-- The above warning supression flag is a temporary kludge.
+-- While working on this module you are encouraged to remove it and fix
+-- any warnings in the module. See
+--     http://hackage.haskell.org/trac/ghc/wiki/WorkingConventions#Warnings
+-- for details
+
 module Simplify ( simplTopBinds, simplExpr ) where
 
 #include "HsVersions.h"
@@ -17,10 +24,10 @@ 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
@@ -31,7 +38,6 @@ import TysPrim                ( realWorldStatePrimTy )
 import PrelInfo                ( realWorldPrimId )
 import BasicTypes      ( TopLevelFlag(..), isTopLevel, 
                          RecFlag(..), isNonRuleLoopBreaker )
-import List            ( nub )
 import Maybes          ( orElse )
 import Outputable
 import Util
@@ -307,46 +313,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.
@@ -371,7 +369,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}
 
@@ -449,6 +451,7 @@ prepareRhs env rhs
        = return (False, env, other)
 \end{code}
 
+
 Note [Float coercions]
 ~~~~~~~~~~~~~~~~~~~~~~
 When we find the binding
@@ -875,7 +878,7 @@ simplNonRecE env bndr (rhs, rhs_se) (bndrs, body) cont
                     (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}
@@ -896,10 +899,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
@@ -956,6 +959,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:
@@ -967,9 +972,9 @@ 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 
@@ -1035,7 +1040,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
@@ -1112,6 +1117,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
@@ -1122,15 +1131,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
@@ -1228,31 +1287,174 @@ 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
@@ -1304,134 +1506,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.
-
-       ; 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 -> []
+       ; (alt_env, scrut', case_bndr') <- simplCaseBinder alt_env scrut case_bndr alts
 
-       -- "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)
+        -> SimplM OutAlt
 
--- Simplify an alternative, returning the type refinement for the 
--- alternative, if the alternative does any refinement at all
-
-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
@@ -1516,8 +1641,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
@@ -1615,7 +1740,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)
@@ -1638,8 +1763,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.