[project @ 1998-12-02 13:17:09 by simonm]
[ghc-hetmet.git] / ghc / compiler / simplCore / SimplCase.lhs
diff --git a/ghc/compiler/simplCore/SimplCase.lhs b/ghc/compiler/simplCore/SimplCase.lhs
deleted file mode 100644 (file)
index 7e47bd4..0000000
+++ /dev/null
@@ -1,967 +0,0 @@
-%
-% (c) The AQUA Project, Glasgow University, 1994-1996
-%
-\section[SimplCase]{Simplification of `case' expression}
-
-Support code for @Simplify@.
-
-\begin{code}
-module SimplCase ( simplCase, bindLargeRhs ) where
-
-#include "HsVersions.h"
-
-import {-# SOURCE #-} Simplify ( simplBind, simplExpr )
-
-import BinderInfo      -- too boring to try to select things...
-import CmdLineOpts     ( SimplifierSwitch(..) )
-import CoreSyn
-import CoreUnfold      ( Unfolding(..) )
-import CoreUtils       ( coreAltsType, nonErrorRHSs, maybeErrorApp,
-                         unTagBindersAlts, unTagBinders, coreExprType
-                       )
-import Id              ( idType, isDataCon, getIdDemandInfo, dataConArgTys,
-                         DataCon, GenId{-instance Eq-},
-                         Id
-                       )
-import IdInfo          ( willBeDemanded, DemandInfo )
-import Literal         ( isNoRepLit, Literal{-instance Eq-} )
-import Maybes          ( maybeToBool )
-import PrelVals                ( voidId )
-import PrimOp          ( primOpOkForSpeculation, PrimOp{-instance Eq-} )
-import SimplVar                ( simplBinder, simplBinders )
-import SimplUtils      ( newId, newIds )
-import SimplEnv
-import SimplMonad
-import Type            ( isUnpointedType, splitAlgTyConApp_maybe, splitAlgTyConApp, mkFunTy, mkFunTys )
-import TyCon           ( isDataTyCon )
-import TysPrim         ( voidTy )
-import Util            ( Eager, runEager, appEager,
-                         isIn, isSingleton, zipEqual, panic, assertPanic )
-import Outputable
-\end{code}
-
-Float let out of case.
-
-\begin{code}
-simplCase :: SimplEnv
-         -> InExpr                                     -- Scrutinee
-         -> (SubstEnvs, InAlts)                        -- Alternatives, and their static environment
-         -> (SimplEnv -> InExpr -> SmplM OutExpr)      -- Rhs handler
-         -> OutType                                    -- Type of result expression
-         -> SmplM OutExpr
-
-simplCase env (Let bind body) alts rhs_c result_ty
-  | not (switchIsSet env SimplNoLetFromCase)
-  =    -- Float the let outside the case scrutinee (if not disabled by flag)
-    tick LetFloatFromCase              `thenSmpl_`
-    simplBind env bind (\env -> simplCase env body alts rhs_c result_ty) result_ty
-\end{code}
-
-OK to do case-of-case if
-
-* we allow arbitrary code duplication
-
-OR
-
-* the inner case has one alternative
-       case (case e of (a,b) -> rhs) of
-        ...
-        pi -> rhsi
-        ...
-  ===>
-       case e of
-         (a,b) -> case rhs of
-                       ...
-                       pi -> rhsi
-                       ...
-
-IF neither of these two things are the case, we avoid code-duplication
-by abstracting the outer rhss wrt the pattern variables.  For example
-
-       case (case e of { p1->rhs1; ...; pn -> rhsn }) of
-         (x,y) -> body
-===>
-       let b = \ x y -> body
-       in
-       case e of
-         p1 -> case rhs1 of (x,y) -> b x y
-         ...
-         pn -> case rhsn of (x,y) -> b x y
-
-
-OK, so outer case expression gets duplicated, but that's all.  Furthermore,
-  (a) the binding for "b" will be let-no-escaped, so no heap allocation
-       will take place; the "call" to b will simply be a stack adjustment
-       and a jump
-  (b) very commonly, at least some of the rhsi's will be constructors, which
-       makes life even simpler.
-
-All of this works equally well if the outer case has multiple rhss.
-
-
-\begin{code}
-simplCase env (Case inner_scrut inner_alts) (subst_envs, outer_alts) rhs_c result_ty
-  | switchIsSet env SimplCaseOfCase
-  =    -- Ha!  Do case-of-case
-    tick CaseOfCase    `thenSmpl_`
-
-    if no_need_to_bind_large_alts
-    then
-       simplCase env inner_scrut (getSubstEnvs env, inner_alts)
-                 (\env' rhs -> simplCase env' rhs (subst_envs, outer_alts) rhs_c result_ty)
-                 result_ty
-    else
-       bindLargeAlts env_alts outer_alts rhs_c result_ty       `thenSmpl` \ (extra_bindings, outer_alts') ->
-       let
-          rhs_c' = \env rhs -> simplExpr env rhs [] result_ty
-       in
-       simplCase env inner_scrut (getSubstEnvs env, inner_alts)
-                 (\env rhs -> simplCase env rhs (subst_envs, outer_alts') rhs_c' result_ty)
-                       -- We used to have "emptySubstEnvs" instead of subst_envs here,
-                       -- but that is *wrong*.  The outer_alts' still have the old
-                       -- binders from outer_alts, with un-substituted types,
-                       -- so we must keep their subst_envs with them.  It does
-                       -- no harm to the freshly-manufactured part of outer_alts',
-                       -- because it'll have nothing in the domain of subst_envs anyway
-                 result_ty
-                                               `thenSmpl` \ case_expr ->
-       returnSmpl (mkCoLetsNoUnboxed extra_bindings case_expr)
-
-  where
-    env_alts = setSubstEnvs env subst_envs
-
-    no_need_to_bind_large_alts = switchIsSet env SimplOkToDupCode ||
-                                isSingleton (nonErrorRHSs inner_alts)
-\end{code}
-
-Case of an application of error.
-
-\begin{code}
-simplCase env scrut alts rhs_c result_ty
-  | maybeToBool maybe_error_app
-  =    -- Look for an application of an error id
-    tick CaseOfError   `thenSmpl_`
-    simplExpr env retyped_error_app [] result_ty
-               -- Ignore rhs_c!
-               -- We must apply simplExpr because "rhs" isn't yet simplified.
-               -- The ice is a little thin because body_ty is an OutType; but it's ok really
-  where
-    maybe_error_app       = maybeErrorApp scrut (Just result_ty)
-    Just retyped_error_app = maybe_error_app
-\end{code}
-
-Finally the default case
-
-\begin{code}
-simplCase env other_scrut (subst_envs, alts) rhs_c result_ty
-  = simplTy env scrut_ty                               `appEager` \ scrut_ty' ->
-    simplExpr env_scrut other_scrut [] scrut_ty'       `thenSmpl` \ scrut' ->
-    completeCase env_alts scrut' alts rhs_c
-  where
-       -- When simplifying the scrutinee of a complete case that
-       -- has no default alternative
-    env_scrut = case alts of
-               AlgAlts _ NoDefault  -> setCaseScrutinee env
-               PrimAlts _ NoDefault -> setCaseScrutinee env
-               other                -> env
-
-    env_alts = setSubstEnvs env subst_envs
-
-    scrut_ty = coreExprType (unTagBinders other_scrut)
-\end{code}
-
-
-%************************************************************************
-%*                                                                     *
-\subsection[Simplify-case]{Completing case-expression simplification}
-%*                                                                     *
-%************************************************************************
-
-\begin{code}
-completeCase
-       :: SimplEnv
-       -> OutExpr                                      -- The already-simplified scrutinee
-       -> InAlts                                       -- The un-simplified alternatives
-       -> (SimplEnv -> InExpr -> SmplM OutExpr)        -- Rhs handler
-       -> SmplM OutExpr        -- The whole case expression
-\end{code}
-
-Scrutinising a literal or constructor.
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-It's an obvious win to do:
-
-       case (C a b) of {...; C p q -> rhs; ...}  ===>   rhs[a/p,b/q]
-
-and the similar thing for primitive case.  If we have
-
-       case x of ...
-
-and x is known to be of constructor form, then we'll already have
-inlined the constructor to give (case (C a b) of ...), so we don't
-need to check for the variable case separately.
-
-Sanity check: we don't have a good
-story to tell about case analysis on NoRep things.  ToDo.
-
-\begin{code}
-completeCase env (Lit lit) alts rhs_c
-  | not (isNoRepLit lit)
-  =    -- Ha!  Select the appropriate alternative
-    tick KnownBranch           `thenSmpl_`
-    completePrimCaseWithKnownLit env lit alts rhs_c
-
-completeCase env expr@(Con con con_args) alts rhs_c
-  =    -- Ha! Staring us in the face -- select the appropriate alternative
-    tick KnownBranch           `thenSmpl_`
-    completeAlgCaseWithKnownCon env con con_args alts rhs_c
-\end{code}
-
-Case elimination
-~~~~~~~~~~~~~~~~
-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!
-
-Actually, we 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:
-\begin{verbatim}
-       case x of
-         0#    -> ...
-         other -> ...(case x of
-                        0#    -> ...
-                        other -> ...) ...
-\end{code}
-Here the inner case can be eliminated.  This really only shows up in
-eliminating error-checking code.
-
-Lastly, we generalise the transformation to handle this:
-
-       case e of       ===> r
-          True  -> r
-          False -> r
-
-We only do this for very cheaply compared r's (constructors, literals
-and variables).  If pedantic bottoms is on, we only do it when the
-scrutinee is a PrimOp which can't fail.
-
-We do it *here*, looking at un-simplified alternatives, because we
-have to check that r doesn't mention the variables bound by the
-pattern in each alternative, so the binder-info is rather useful.
-
-So the case-elimination algorithm is:
-
-       1. Eliminate alternatives which can't match
-
-       2. Check whether all the remaining alternatives
-               (a) do not mention in their rhs any of the variables bound in their pattern
-          and  (b) have equal rhss
-
-       3. Check we can safely ditch the case:
-                  * PedanticBottoms is off,
-               or * the scrutinee is an already-evaluated variable
-               or * the scrutinee is a primop which is ok for speculation
-                       -- ie we want to preserve divide-by-zero errors, and
-                       -- calls to error itself!
-
-               or * [Prim cases] the scrutinee is a primitive variable
-
-               or * [Alg cases] the scrutinee is a variable and
-                    either * the rhs is the same variable
-                       (eg case x of C a b -> x  ===>   x)
-                    or     * there is only one alternative, the default alternative,
-                               and the binder is used strictly in its scope.
-                               [NB this is helped by the "use default binder where
-                                possible" transformation; see below.]
-
-
-If so, then we can replace the case with one of the rhss.
-
-\begin{code}
-completeCase env scrut alts rhs_c
-  | switchIsSet env SimplDoCaseElim &&
-
-    binders_unused &&
-
-    all_rhss_same &&
-
-    (not  (switchIsSet env SimplPedanticBottoms) ||
-     scrut_is_evald ||
-     scrut_is_eliminable_primitive ||
-     rhs1_is_scrutinee ||
-     scrut_is_var_and_single_strict_default
-     )
-
-  = tick CaseElim      `thenSmpl_`
-    rhs_c new_env rhs1
-  where
-       -- Find the non-excluded rhss of the case; always at least one
-    (rhs1:rhss)   = possible_rhss
-    all_rhss_same = all (cheap_eq rhs1) rhss
-
-       -- Find the reduced set of possible rhss, along with an indication of
-       -- whether none of their binders are used
-    (binders_unused, possible_rhss, new_env)
-      = case alts of
-         PrimAlts alts deflt -> (deflt_binder_unused,  -- No binders other than deflt
-                                   deflt_rhs ++ rhss,
-                                   new_env)
-           where
-             (deflt_binder_unused, deflt_rhs, new_env) = elim_deflt_binder deflt
-
-               -- Eliminate unused rhss if poss
-             rhss = case scrut_form of
-                       OtherLit not_these -> [rhs | (alt_lit,rhs) <- alts,
-                                                    not (alt_lit `is_elem` not_these)
-                                             ]
-                       other -> [rhs | (_,rhs) <- alts]
-
-         AlgAlts alts deflt -> (deflt_binder_unused && all alt_binders_unused possible_alts,
-                                  deflt_rhs ++ [rhs | (_,_,rhs) <- possible_alts],
-                                  new_env)
-           where
-             (deflt_binder_unused, deflt_rhs, new_env) = elim_deflt_binder deflt
-
-               -- Eliminate unused alts if poss
-             possible_alts = case scrut_form of
-                               OtherCon not_these ->
-                                               -- Remove alts which can't match
-                                       [alt | alt@(alt_con,_,_) <- alts,
-                                              not (alt_con `is_elem` not_these)]
-
-                               other -> alts
-
-             alt_binders_unused (con, args, rhs) = all is_dead args
-             is_dead (_, DeadCode) = True
-             is_dead other_arg     = False
-
-       -- If the scrutinee is a variable, look it up to see what we know about it
-    scrut_form = case scrut of
-                 Var v -> lookupUnfolding env v
-                 other -> NoUnfolding
-
-       -- If the scrut is already eval'd then there's no worry about
-       -- eliminating the case
-    scrut_is_evald = isEvaluated scrut_form
-
-    scrut_is_eliminable_primitive
-      = case scrut of
-          Prim op _ -> primOpOkForSpeculation op
-          Var _     -> case alts of
-                         PrimAlts _ _ -> True  -- Primitive, hence non-bottom
-                         AlgAlts _ _  -> False -- Not primitive
-          other     -> False
-
-       -- case v of w -> e{strict in w}  ===>   e[v/w]
-    scrut_is_var_and_single_strict_default
-      = case scrut of
-         Var _ -> case alts of
-                       AlgAlts [] (BindDefault (v,_) _) -> willBeDemanded (getIdDemandInfo v)
-                       other -> False
-         other -> False
-
-    elim_deflt_binder NoDefault                         -- No Binder
-       = (True, [], env)
-    elim_deflt_binder (BindDefault (id, DeadCode) rhs) -- Binder unused
-       = (True, [rhs], env)
-    elim_deflt_binder (BindDefault used_binder rhs)     -- Binder used
-       = case scrut of
-               Var v ->        -- Binder used, but can be eliminated in favour of scrut
-                          (True, [rhs], bindIdToAtom env used_binder (VarArg v))
-               non_var ->      -- Binder used, and can't be elimd
-                          (False, [rhs], env)
-
-       -- Check whether the chosen unique rhs (ie rhs1) is the same as
-       -- the scrutinee.  Remember that the rhs is as yet unsimplified.
-    rhs1_is_scrutinee = case (scrut, rhs1) of
-                         (Var scrut_var, Var rhs_var)
-                               -> case (lookupIdSubst env rhs_var) of
-                                   Nothing                  -> rhs_var  == scrut_var
-                                   Just (SubstVar rhs_var') -> rhs_var' == scrut_var
-                                   other                    -> False
-                         other -> False
-
-    is_elem x ys = isIn "completeCase" x ys
-\end{code}
-
-Scrutinising anything else.  If it's a variable, it can't be bound to a
-constructor or literal, because that would have been inlined
-
-\begin{code}
-completeCase env scrut alts rhs_c
-  = simplAlts env scrut alts rhs_c     `thenSmpl` \ alts' ->
-    mkCoCase env scrut alts'
-\end{code}
-
-
-
-
-\begin{code}
-bindLargeAlts :: SimplEnv
-             -> InAlts
-             -> (SimplEnv -> InExpr -> SmplM OutExpr)          -- Old rhs handler
-             -> OutType                                        -- Result type
-             -> SmplM ([OutBinding],   -- Extra bindings
-                       InAlts)         -- Modified alts
-
-bindLargeAlts env the_lot@(AlgAlts alts deflt) rhs_c rhs_ty
-  = mapAndUnzipSmpl do_alt alts                        `thenSmpl` \ (alt_bindings, alts') ->
-    bindLargeDefault env deflt rhs_ty rhs_c    `thenSmpl` \ (deflt_bindings, deflt') ->
-    returnSmpl (deflt_bindings ++ alt_bindings, AlgAlts alts' deflt')
-  where
-    do_alt (con,args,rhs) = bindLargeRhs env args rhs_ty
-                               (\env -> rhs_c env rhs) `thenSmpl` \ (bind,rhs') ->
-                           returnSmpl (bind, (con,args,rhs'))
-
-bindLargeAlts env the_lot@(PrimAlts alts deflt) rhs_c rhs_ty
-  = mapAndUnzipSmpl do_alt alts                        `thenSmpl` \ (alt_bindings, alts') ->
-    bindLargeDefault env deflt rhs_ty rhs_c    `thenSmpl` \ (deflt_bindings, deflt') ->
-    returnSmpl (deflt_bindings ++ alt_bindings, PrimAlts alts' deflt')
-  where
-    do_alt (lit,rhs) = bindLargeRhs env [] rhs_ty
-                               (\env -> rhs_c env rhs) `thenSmpl` \ (bind,rhs') ->
-                      returnSmpl (bind, (lit,rhs'))
-
-bindLargeDefault env NoDefault rhs_ty rhs_c
-  = returnSmpl ([], NoDefault)
-bindLargeDefault env (BindDefault binder rhs) rhs_ty rhs_c
-  = bindLargeRhs env [binder] rhs_ty
-                (\env -> rhs_c env rhs) `thenSmpl` \ (bind,rhs') ->
-    returnSmpl ([bind], BindDefault binder rhs')
-\end{code}
-
-       bindLargeRhs env [x1,..,xn] rhs rhs_ty rhs_c
-        | otherwise        = (rhs_id = \x1..xn -> rhs_c rhs,
-                              rhs_id x1 .. xn)
-
-\begin{code}
-bindLargeRhs :: SimplEnv
-            -> [InBinder]      -- The args wrt which the rhs should be abstracted
-            -> OutType
-            -> (SimplEnv -> SmplM OutExpr)             -- Rhs handler
-            -> SmplM (OutBinding,      -- New bindings (singleton or empty)
-                      InExpr)          -- Modified rhs
-
-bindLargeRhs env args rhs_ty rhs_c
-  | null used_args && isUnpointedType rhs_ty
-       -- If we try to lift a primitive-typed something out
-       -- for let-binding-purposes, we will *caseify* it (!),
-       -- with potentially-disastrous strictness results.  So
-       -- instead we turn it into a function: \v -> e
-       -- where v::Void.  Since arguments of type
-       -- VoidPrim don't generate any code, this gives the
-       -- desired effect.
-       --
-       -- The general structure is just the same as for the common "otherwise~ case
-  = newId prim_rhs_fun_ty      `thenSmpl` \ prim_rhs_fun_id ->
-    newId voidTy               `thenSmpl` \ void_arg_id ->
-    rhs_c env                  `thenSmpl` \ prim_new_body ->
-
-    returnSmpl (NonRec prim_rhs_fun_id (mkValLam [void_arg_id] prim_new_body),
-               App (Var prim_rhs_fun_id) (VarArg voidId))
-
-  | otherwise
-  =    -- Generate the rhs
-    simplBinders env used_args `thenSmpl` \ (new_env, used_args') ->
-    let
-       rhs_fun_ty :: OutType
-       rhs_fun_ty = mkFunTys (map idType used_args') rhs_ty
-    in
-
-       -- Make the new binding Id.  NB: it's an OutId
-    newId rhs_fun_ty           `thenSmpl` \ rhs_fun_id ->
-    rhs_c new_env              `thenSmpl` \ rhs' ->
-    let
-       final_rhs = mkValLam used_args' rhs'
-    in
-    returnSmpl (NonRec rhs_fun_id final_rhs,
-               foldl App (Var rhs_fun_id) used_arg_atoms)
-       -- This is slightly wierd. We're retuning an OutId as part of the
-       -- modified rhs, which is meant to be an InExpr. However, that's ok, because when
-       -- it's processed the OutId won't be found in the environment, so it
-       -- will be left unmodified.
-  where
-
-    used_args      = [arg | arg@(_,usage) <- args, not (dead usage)]
-    used_arg_atoms = [VarArg arg_id | (arg_id,_) <- used_args]
-    dead DeadCode  = True
-    dead other     = False
-
-    prim_rhs_fun_ty = mkFunTy voidTy rhs_ty
-\end{code}
-
-Case alternatives when we don't know the scrutinee
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-A special case for case default.  If we have
-\begin{verbatim}
-case x of
-  p1 -> e1
-  y  -> default_e
-\end{verbatim}
-it is best to make sure that \tr{default_e} mentions \tr{x} in
-preference to \tr{y}.  The code generator can do a cheaper job if it
-doesn't have to come up with a binding for \tr{y}.
-
-\begin{code}
-simplAlts :: SimplEnv
-         -> OutExpr                    -- Simplified scrutinee;
-                                       -- only of interest if its a var,
-                                       -- in which case we record its form
-         -> InAlts
-         -> (SimplEnv -> InExpr -> SmplM OutExpr)      -- Rhs handler
-         -> SmplM OutAlts
--- For single-constructor types
---     case e of y -> b    ===>   case e of (a,b) -> let y = (a,b) in b
-
-simplAlts env scrut (AlgAlts [] (BindDefault bndr@(id,occ_info) rhs)) rhs_c
-  | maybeToBool maybe_data_ty && 
-    not (null cons)           && -- Not an abstract type (can arise if we're pruning tydecl imports)
-    null other_cons           &&
-    isDataTyCon tycon  -- doesn't apply to (constructor-less) newtypes
-  = newIds inst_con_arg_tys    `thenSmpl` \ new_bindees ->
-    let
-       new_args = [ (b, bad_occ_info) | b <- new_bindees ]
-       con_app  = mkCon con ty_args (map VarArg new_bindees)
-       new_rhs  = Let (NonRec bndr con_app) rhs
-    in
-    simplAlts env scrut (AlgAlts [(con,new_args,new_rhs)] NoDefault) rhs_c
-  where
-    maybe_data_ty              = splitAlgTyConApp_maybe (idType id)
-    Just (tycon, ty_args, cons)        = maybe_data_ty
-    (con:other_cons)           = cons
-    inst_con_arg_tys           = dataConArgTys con ty_args
-    bad_occ_info               = ManyOcc 0     -- Non-committal!
-
-simplAlts env scrut (AlgAlts alts deflt) rhs_c
-  = mapSmpl do_alt alts                                        `thenSmpl` \ alts' ->
-    simplDefault env scrut deflt deflt_form rhs_c      `thenSmpl` \ deflt' ->
-    returnSmpl (AlgAlts alts' deflt')
-  where
-    deflt_form = OtherCon [con | (con,_,_) <- alts]
-    do_alt (con, con_args, rhs)
-      = simplBinders env con_args                              `thenSmpl` \ (env1, con_args') ->
-       let
-           new_env = case scrut of
-                      Var v -> extendEnvGivenNewRhs env1 v (Con con args)
-                            where
-                               (_, ty_args, _) = splitAlgTyConApp (idType v)
-                               args = map TyArg ty_args ++ map VarArg con_args'
-
-                      other -> env1
-       in
-       rhs_c new_env rhs                               `thenSmpl` \ rhs' ->
-       returnSmpl (con, con_args', rhs')
-
-simplAlts env scrut (PrimAlts alts deflt) rhs_c
-  = mapSmpl do_alt alts                                        `thenSmpl` \ alts' ->
-    simplDefault env scrut deflt deflt_form rhs_c      `thenSmpl` \ deflt' ->
-    returnSmpl (PrimAlts alts' deflt')
-  where
-    deflt_form = OtherLit [lit | (lit,_) <- alts]
-    do_alt (lit, rhs)
-      = let
-           new_env = case scrut of
-                       Var v -> extendEnvGivenNewRhs env v (Lit lit)
-                       other -> env
-       in
-       rhs_c new_env rhs                               `thenSmpl` \ rhs' ->
-       returnSmpl (lit, rhs')
-\end{code}
-
-Use default binder where possible
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-There's one complication when simplifying the default clause of
-a case expression.  If we see
-
-       case x of
-         x' -> ...x...x'...
-
-we'd like to convert it to
-
-       case x of
-         x' -> ...x'...x'...
-
-Reason 1: then there might be just one occurrence of x, and it can be
-inlined as the case scrutinee.  So we spot this case when dealing with
-the default clause, and add a binding to the environment mapping x to
-x'.
-
-Reason 2: if the body is strict in x' then we can eliminate the
-case altogether. By using x' in preference to x we give the max chance
-of the strictness analyser finding that the body is strict in x'.
-
-On the other hand, if x does *not* get inlined, then we'll actually
-get somewhat better code from the former expression.  So when
-doing Core -> STG we convert back!
-
-\begin{code}
-simplDefault
-       :: SimplEnv
-       -> OutExpr                      -- Simplified scrutinee
-       -> InDefault                    -- Default alternative to be completed
-       -> Unfolding                    -- Gives form of scrutinee
-       -> (SimplEnv -> InExpr -> SmplM OutExpr)                -- Old rhs handler
-       -> SmplM OutDefault
-
-simplDefault env scrut NoDefault form rhs_c
-  = returnSmpl NoDefault
-
--- Special case for variable scrutinee; see notes above.
-simplDefault env (Var scrut_var) (BindDefault binder@(_,occ_info) rhs) 
-            info_from_this_case rhs_c
-  = simplBinder env binder     `thenSmpl` \ (env1, binder') ->
-    let
-      env2 = extendEnvGivenNewRhs env1 scrut_var (Var binder')
-
-       -- Add form details for the default binder
-      scrut_unf = lookupUnfolding env scrut_var
-      new_env   = extendEnvGivenUnfolding env2 binder' noBinderInfo scrut_unf
-                       -- Use noBinderInfo rather than occ_info because we've
-                       -- added more occurrences by binding the scrut_var to it
-    in
-    rhs_c new_env rhs                  `thenSmpl` \ rhs' ->
-    returnSmpl (BindDefault binder' rhs')
-
-simplDefault env scrut (BindDefault binder@(_,occ_info) rhs) 
-            info_from_this_case rhs_c
-  = simplBinder env binder     `thenSmpl` \ (env1, binder') ->
-    let
-       new_env = extendEnvGivenUnfolding env1 binder' occ_info info_from_this_case
-    in
-    rhs_c new_env rhs                  `thenSmpl` \ rhs' ->
-    returnSmpl (BindDefault binder' rhs')
-\end{code}
-
-Case alternatives when we know what the scrutinee is
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-\begin{code}
-completePrimCaseWithKnownLit
-       :: SimplEnv
-       -> Literal
-       -> InAlts
-       -> (SimplEnv -> InExpr -> SmplM OutExpr)        -- Rhs handler
-       -> SmplM OutExpr
-
-completePrimCaseWithKnownLit env lit (PrimAlts alts deflt) rhs_c
-  = search_alts alts
-  where
-    search_alts :: [(Literal, InExpr)] -> SmplM OutExpr
-
-    search_alts ((alt_lit, rhs) : _)
-      | alt_lit == lit
-      =        -- Matching alternative!
-       rhs_c env rhs
-
-    search_alts (_ : other_alts)
-      =        -- This alternative doesn't match; keep looking
-       search_alts other_alts
-
-    search_alts []
-      = case deflt of
-         NoDefault      ->     -- Blargh!
-           panic "completePrimCaseWithKnownLit: No matching alternative and no default"
-
-         BindDefault binder rhs ->     -- OK, there's a default case
-                                       -- Just bind the Id to the atom and continue
-           let
-               new_env = bindIdToAtom env binder (LitArg lit)
-           in
-           rhs_c new_env rhs
-\end{code}
-
-@completeAlgCaseWithKnownCon@: We know the constructor, so we can
-select one case alternative (or default).  If we choose the default:
-we do different things depending on whether the constructor was
-staring us in the face (e.g., \tr{case (p:ps) of {y -> ...}})
-[let-bind it] or we just know the \tr{y} is now the same as some other
-var [substitute \tr{y} out of existence].
-
-\begin{code}
-completeAlgCaseWithKnownCon
-       :: SimplEnv
-       -> DataCon -> [InArg]
-               -- Scrutinee is (con, type, value arguments)
-       -> InAlts
-       -> (SimplEnv -> InExpr -> SmplM OutExpr)        -- Rhs handler
-       -> SmplM OutExpr
-
-completeAlgCaseWithKnownCon env con con_args a@(AlgAlts alts deflt) rhs_c
-  = ASSERT(isDataCon con)
-    search_alts alts
-  where
-    search_alts :: [(Id, [InBinder], InExpr)] -> SmplM OutExpr
-
-    search_alts ((alt_con, alt_args, rhs) : _)
-      | alt_con == con
-      =        -- Matching alternative!
-       let
-           val_args = filter isValArg con_args
-           new_env  = foldr bind env (zipEqual "SimplCase" alt_args val_args)
-           bind (bndr, atom) env = bindIdToAtom env bndr atom
-       in
-       rhs_c new_env rhs
-
-    search_alts (_ : other_alts)
-      =        -- This alternative doesn't match; keep looking
-       search_alts other_alts
-
-    search_alts []
-      =        -- No matching alternative
-       case deflt of
-         NoDefault      ->     -- Blargh!
-           pprPanic "completeAlgCaseWithKnownCon: No matching alternative and no default"
-                    (ppr con <+> ppr con_args $$ ppr a)
-
-         BindDefault binder@(_,occ_info) rhs ->        -- OK, there's a default case
-                       -- let-bind the binder to the constructor
-               simplBinder env binder          `thenSmpl` \ (env1, id') ->
-               let
-                   new_env = extendEnvGivenBinding env1 occ_info id' (Con con con_args)
-               in
-               rhs_c new_env rhs               `thenSmpl` \ rhs' ->
-               returnSmpl (Let (NonRec id' (Con con con_args)) rhs')
-\end{code}
-
-Case absorption and identity-case elimination
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-\begin{code}
-mkCoCase :: SimplEnv -> OutExpr -> OutAlts -> SmplM OutExpr
-\end{code}
-
-@mkCoCase@ tries the following transformation (if possible):
-
-case v of                 ==>   case v of
-  p1 -> rhs1                     p1 -> rhs1
-  ...                            ...
-  pm -> rhsm                      pm -> rhsm
-  d  -> case v of                 pn -> rhsn[v/d]  {or (alg)  let d=v in rhsn}
-                                                  {or (prim) case v of d -> rhsn}
-         pn -> rhsn              ...
-         ...                     po -> rhso[v/d]
-         po -> rhso              d  -> rhsd[d/d'] {or let d'=d in rhsd}
-         d' -> rhsd
-
-which merges two cases in one case when -- the default alternative of
-the outer case scrutises the same variable as the outer case This
-transformation is called Case Merging.  It avoids that the same
-variable is scrutinised multiple times.
-
-There's a closely-related transformation:
-
-case e of                 ==>   case e of
-  p1 -> rhs1                     p1 -> rhs1
-  ...                            ...
-  pm -> rhsm                      pm -> rhsm
-  d  -> case d of                 pn -> let d = pn in rhsn
-         pn -> rhsn              ...
-         ...                     po -> let d = po in rhso
-         po -> rhso              d  -> rhsd[d/d'] {or let d'=d in rhsd}
-         d' -> rhsd
-
-Here, the let's are essential, because d isn't in scope any more.
-Sigh.  Of course, they may be unused, in which case they'll be
-eliminated on the next round.  Unfortunately, we can't figure out
-whether or not they are used at this juncture.
-
-NB: The binder in a BindDefault USED TO BE guaranteed unused if the
-scrutinee is a variable, because it'll be mapped to the scrutinised
-variable.  Hence the [v/d] substitions can be omitted.
-
-ALAS, now the default binder is used by preference, so we have to
-generate trivial lets to express the substitutions, which will be
-eliminated on the next pass.
-
-The following code handles *both* these transformations (one
-equation for AlgAlts, one for PrimAlts):
-
-\begin{code}
-mkCoCase env scrut (AlgAlts outer_alts
-                         (BindDefault deflt_var
-                                        (Case (Var scrut_var')
-                                                (AlgAlts inner_alts inner_deflt))))
-  |  switchIsSet env SimplCaseMerge &&
-     ((scrut_is_var && scrut_var == scrut_var')        ||      -- First transformation
-      deflt_var == scrut_var')                         -- Second transformation
-  =    -- Aha! The default-absorption rule applies
-    tick CaseMerge     `thenSmpl_`
-    returnSmpl (Case scrut (AlgAlts (outer_alts ++ munged_reduced_inner_alts)
-                            (munge_alg_deflt deflt_var inner_deflt)))
-       -- NB: see comment in this location for the PrimAlts case
-  where
-       -- Check scrutinee
-    scrut_is_var = case scrut of {Var v -> True; other -> False}
-    scrut_var    = case scrut of Var v -> v
-
-       --  Eliminate any inner alts which are shadowed by the outer ones
-    reduced_inner_alts = [alt | alt@(con,_,_) <- inner_alts,
-                               not (con `is_elem` outer_cons)]
-    outer_cons = [con | (con,_,_) <- outer_alts]
-    is_elem = isIn "mkAlgAlts"
-
-       -- Add the lets if necessary
-    munged_reduced_inner_alts = map munge_alt reduced_inner_alts
-
-    munge_alt (con, args, rhs) = (con, args, Let (NonRec deflt_var v) rhs)
-       where
-        v | scrut_is_var = Var scrut_var
-          | otherwise    = Con con (map TyArg arg_tys ++ map VarArg args)
-
-    arg_tys = case (splitAlgTyConApp (idType deflt_var)) of
-               (_, arg_tys, _) -> arg_tys
-
-mkCoCase env scrut (PrimAlts
-                 outer_alts
-                 (BindDefault deflt_var (Case
-                                             (Var scrut_var')
-                                             (PrimAlts inner_alts inner_deflt))))
-  |  switchIsSet env SimplCaseMerge &&
-     ((scrut_is_var && scrut_var == scrut_var') ||
-      deflt_var == scrut_var')
-  =    -- Aha! The default-absorption rule applies
-    tick CaseMerge     `thenSmpl_`
-    returnSmpl (Case scrut (PrimAlts (outer_alts ++ munged_reduced_inner_alts)
-                            (munge_prim_deflt deflt_var inner_deflt)))
-
-       -- Nota Bene: we don't recurse to mkCoCase again, because the
-       -- default will now have a binding in it that prevents
-       -- mkCoCase doing anything useful.  Much worse, in this
-       -- PrimAlts case the binding in the default branch is another
-       -- Case, so if we recurse to mkCoCase we will get into an
-       -- infinite loop.
-       --
-       -- ToDo: think of a better way to do this.  At the moment
-       -- there is at most one case merge per round.  That's probably
-       -- plenty but it seems unclean somehow.
-  where
-       -- Check scrutinee
-    scrut_is_var = case scrut of {Var v -> True; other -> False}
-    scrut_var    = case scrut of Var v -> v
-
-       --  Eliminate any inner alts which are shadowed by the outer ones
-    reduced_inner_alts = [alt | alt@(lit,_) <- inner_alts,
-                               not (lit `is_elem` outer_lits)]
-    outer_lits = [lit | (lit,_) <- outer_alts]
-    is_elem = isIn "mkPrimAlts"
-
-       -- Add the lets (well cases actually) if necessary
-       -- The munged alternative looks like
-       --      lit -> case lit of d -> rhs
-       -- The next pass will certainly eliminate the inner case, but
-       -- it isn't easy to do so right away.
-    munged_reduced_inner_alts = map munge_alt reduced_inner_alts
-
-    munge_alt (lit, rhs)
-      | scrut_is_var = (lit, Case (Var scrut_var)
-                                   (PrimAlts [] (BindDefault deflt_var rhs)))
-      | otherwise = (lit, Case (Lit lit)
-                                (PrimAlts [] (BindDefault deflt_var rhs)))
-\end{code}
-
-Now the identity-case transformation:
-
-       case e of               ===> e
-               True -> True;
-               False -> False
-
-and similar friends.
-
-\begin{code}
-mkCoCase env scrut alts
-  | identity_alts alts
-  = tick CaseIdentity          `thenSmpl_`
-    returnSmpl scrut
-  where
-    identity_alts (AlgAlts alts deflt)  = all identity_alg_alt  alts && identity_deflt deflt
-    identity_alts (PrimAlts alts deflt) = all identity_prim_alt alts && identity_deflt deflt
-
-    identity_alg_alt (con, args, Con con' args')
-        = con == con'
-          && and (zipWith eq_arg args args')
-          && length args == length args'
-    identity_alg_alt other
-        = False
-
-    identity_prim_alt (lit, Lit lit') = lit == lit'
-    identity_prim_alt other           = False
-
-        -- For the default case we want to spot both
-        --     x -> x
-        -- and
-        --     case y of { ... ; x -> y }
-        -- as "identity" defaults
-    identity_deflt NoDefault = True
-    identity_deflt (BindDefault binder (Var x)) = x == binder ||
-                                                     case scrut of
-                                                        Var y -> y == x
-                                                        other   -> False
-    identity_deflt _ = False
-
-    eq_arg binder (VarArg x) = binder == x
-    eq_arg _      _           = False
-\end{code}
-
-The catch-all case
-
-\begin{code}
-mkCoCase env other_scrut other_alts = returnSmpl (Case other_scrut other_alts)
-\end{code}
-
-Boring local functions used above.  They simply introduce a trivial binding
-for the binder, d', in an inner default; either
-       let d' = deflt_var in rhs
-or
-       case deflt_var of d' -> rhs
-depending on whether it's an algebraic or primitive case.
-
-\begin{code}
-munge_prim_deflt _ NoDefault = NoDefault
-
-munge_prim_deflt deflt_var (BindDefault d' rhs)
-  =   BindDefault deflt_var (Case (Var deflt_var)
-                                     (PrimAlts [] (BindDefault d' rhs)))
-
-munge_alg_deflt _ NoDefault = NoDefault
-
-munge_alg_deflt deflt_var (BindDefault d' rhs)
-  =   BindDefault deflt_var (Let (NonRec d' (Var deflt_var)) rhs)
-
--- This line caused a generic version of munge_deflt (ie one used for
--- both alg and prim) to space leak massively.  No idea why.
---  = BindDefault deflt_var (mkCoLetUnboxedToCase (NonRec d' (Var deflt_var)) rhs)
-\end{code}
-
-\begin{code}
-cheap_eq :: InExpr -> InExpr -> Bool
-       -- A cheap equality test which bales out fast!
-
-cheap_eq (Var v1) (Var v2) = v1==v2
-cheap_eq (Lit l1) (Lit l2) = l1==l2
-cheap_eq (Con con1 args1) (Con con2 args2)
-  = con1 == con2 && args1 `eq_args` args2
-
-cheap_eq (Prim op1 args1) (Prim op2 args2)
-  = op1 ==op2 && args1 `eq_args` args2
-
-cheap_eq (App f1 a1) (App f2 a2)
-  = f1 `cheap_eq` f2 && a1 `eq_arg` a2
-
-cheap_eq _ _ = False
-
--- ToDo: make CoreArg an instance of Eq
-eq_args (a1:as1) (a2:as2) = a1 `eq_arg` a2 && as1 `eq_args` as2
-eq_args []      []       = True
-eq_args _       _        = False
-
-eq_arg (LitArg          l1) (LitArg   l2) = l1 == l2
-eq_arg (VarArg          v1) (VarArg   v2) = v1 == v2
-eq_arg (TyArg           t1) (TyArg    t2) = t1 == t2
-eq_arg _            _             =  False
-\end{code}