summaryrefslogtreecommitdiff
path: root/compiler/coreSyn/CorePrep.lhs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/coreSyn/CorePrep.lhs')
-rw-r--r--compiler/coreSyn/CorePrep.lhs859
1 files changed, 859 insertions, 0 deletions
diff --git a/compiler/coreSyn/CorePrep.lhs b/compiler/coreSyn/CorePrep.lhs
new file mode 100644
index 0000000000..e5165f0ebe
--- /dev/null
+++ b/compiler/coreSyn/CorePrep.lhs
@@ -0,0 +1,859 @@
+%
+% (c) The University of Glasgow, 1994-2000
+%
+\section{Core pass to saturate constructors and PrimOps}
+
+\begin{code}
+module CorePrep (
+ corePrepPgm, corePrepExpr
+ ) where
+
+#include "HsVersions.h"
+
+import CoreUtils( exprType, exprIsHNF, etaExpand, exprArity, exprOkForSpeculation )
+import CoreFVs ( exprFreeVars )
+import CoreLint ( endPass )
+import CoreSyn
+import Type ( Type, applyTy, splitFunTy_maybe,
+ isUnLiftedType, isUnboxedTupleType, seqType )
+import TyCon ( TyCon, tyConDataCons )
+import NewDemand ( Demand, isStrictDmd, lazyDmd, StrictSig(..), DmdType(..) )
+import Var ( Var, Id, setVarUnique )
+import VarSet
+import VarEnv
+import Id ( mkSysLocal, idType, idNewDemandInfo, idArity, setIdUnfolding, setIdType,
+ isFCallId, isGlobalId,
+ isLocalId, hasNoBinding, idNewStrictness,
+ isPrimOpId_maybe
+ )
+import DataCon ( isVanillaDataCon, dataConWorkId )
+import PrimOp ( PrimOp( DataToTagOp ) )
+import BasicTypes ( TopLevelFlag(..), isTopLevel, isNotTopLevel,
+ RecFlag(..), isNonRec
+ )
+import UniqSupply
+import Maybes
+import OrdList
+import ErrUtils
+import DynFlags
+import Util ( listLengthCmp )
+import Outputable
+\end{code}
+
+-- ---------------------------------------------------------------------------
+-- Overview
+-- ---------------------------------------------------------------------------
+
+The goal of this pass is to prepare for code generation.
+
+1. Saturate constructor and primop applications.
+
+2. Convert to A-normal form:
+
+ * Use case for strict arguments:
+ f E ==> case E of x -> f x
+ (where f is strict)
+
+ * Use let for non-trivial lazy arguments
+ f E ==> let x = E in f x
+ (were f is lazy and x is non-trivial)
+
+3. Similarly, convert any unboxed lets into cases.
+ [I'm experimenting with leaving 'ok-for-speculation'
+ rhss in let-form right up to this point.]
+
+4. Ensure that lambdas only occur as the RHS of a binding
+ (The code generator can't deal with anything else.)
+
+5. [Not any more; nuked Jun 2002] Do the seq/par munging.
+
+6. Clone all local Ids.
+ This means that all such Ids are unique, rather than the
+ weaker guarantee of no clashes which the simplifier provides.
+ And that is what the code generator needs.
+
+ We don't clone TyVars. The code gen doesn't need that,
+ and doing so would be tiresome because then we'd need
+ to substitute in types.
+
+
+7. Give each dynamic CCall occurrence a fresh unique; this is
+ rather like the cloning step above.
+
+8. Inject bindings for the "implicit" Ids:
+ * Constructor wrappers
+ * Constructor workers
+ * Record selectors
+ We want curried definitions for all of these in case they
+ aren't inlined by some caller.
+
+This is all done modulo type applications and abstractions, so that
+when type erasure is done for conversion to STG, we don't end up with
+any trivial or useless bindings.
+
+
+
+-- -----------------------------------------------------------------------------
+-- Top level stuff
+-- -----------------------------------------------------------------------------
+
+\begin{code}
+corePrepPgm :: DynFlags -> [CoreBind] -> [TyCon] -> IO [CoreBind]
+corePrepPgm dflags binds data_tycons
+ = do showPass dflags "CorePrep"
+ us <- mkSplitUniqSupply 's'
+
+ let implicit_binds = mkDataConWorkers data_tycons
+ -- NB: we must feed mkImplicitBinds through corePrep too
+ -- so that they are suitably cloned and eta-expanded
+
+ binds_out = initUs_ us (
+ corePrepTopBinds binds `thenUs` \ floats1 ->
+ corePrepTopBinds implicit_binds `thenUs` \ floats2 ->
+ returnUs (deFloatTop (floats1 `appendFloats` floats2))
+ )
+
+ endPass dflags "CorePrep" Opt_D_dump_prep binds_out
+ return binds_out
+
+corePrepExpr :: DynFlags -> CoreExpr -> IO CoreExpr
+corePrepExpr dflags expr
+ = do showPass dflags "CorePrep"
+ us <- mkSplitUniqSupply 's'
+ let new_expr = initUs_ us (corePrepAnExpr emptyCorePrepEnv expr)
+ dumpIfSet_dyn dflags Opt_D_dump_prep "CorePrep"
+ (ppr new_expr)
+ return new_expr
+\end{code}
+
+-- -----------------------------------------------------------------------------
+-- Implicit bindings
+-- -----------------------------------------------------------------------------
+
+Create any necessary "implicit" bindings for data con workers. We
+create the rather strange (non-recursive!) binding
+
+ $wC = \x y -> $wC x y
+
+i.e. a curried constructor that allocates. This means that we can
+treat the worker for a constructor like any other function in the rest
+of the compiler. The point here is that CoreToStg will generate a
+StgConApp for the RHS, rather than a call to the worker (which would
+give a loop). As Lennart says: the ice is thin here, but it works.
+
+Hmm. Should we create bindings for dictionary constructors? They are
+always fully applied, and the bindings are just there to support
+partial applications. But it's easier to let them through.
+
+\begin{code}
+mkDataConWorkers data_tycons
+ = [ NonRec id (Var id) -- The ice is thin here, but it works
+ | tycon <- data_tycons, -- CorePrep will eta-expand it
+ data_con <- tyConDataCons tycon,
+ let id = dataConWorkId data_con ]
+\end{code}
+
+
+\begin{code}
+-- ---------------------------------------------------------------------------
+-- Dealing with bindings
+-- ---------------------------------------------------------------------------
+
+data FloatingBind = FloatLet CoreBind
+ | FloatCase Id CoreExpr Bool
+ -- The bool indicates "ok-for-speculation"
+
+data Floats = Floats OkToSpec (OrdList FloatingBind)
+
+-- Can we float these binds out of the rhs of a let? We cache this decision
+-- to avoid having to recompute it in a non-linear way when there are
+-- deeply nested lets.
+data OkToSpec
+ = NotOkToSpec -- definitely not
+ | OkToSpec -- yes
+ | IfUnboxedOk -- only if floating an unboxed binding is ok
+
+emptyFloats :: Floats
+emptyFloats = Floats OkToSpec nilOL
+
+addFloat :: Floats -> FloatingBind -> Floats
+addFloat (Floats ok_to_spec floats) new_float
+ = Floats (combine ok_to_spec (check new_float)) (floats `snocOL` new_float)
+ where
+ check (FloatLet _) = OkToSpec
+ check (FloatCase _ _ ok_for_spec)
+ | ok_for_spec = IfUnboxedOk
+ | otherwise = NotOkToSpec
+ -- The ok-for-speculation flag says that it's safe to
+ -- float this Case out of a let, and thereby do it more eagerly
+ -- We need the top-level flag because it's never ok to float
+ -- an unboxed binding to the top level
+
+unitFloat :: FloatingBind -> Floats
+unitFloat = addFloat emptyFloats
+
+appendFloats :: Floats -> Floats -> Floats
+appendFloats (Floats spec1 floats1) (Floats spec2 floats2)
+ = Floats (combine spec1 spec2) (floats1 `appOL` floats2)
+
+concatFloats :: [Floats] -> Floats
+concatFloats = foldr appendFloats emptyFloats
+
+combine NotOkToSpec _ = NotOkToSpec
+combine _ NotOkToSpec = NotOkToSpec
+combine IfUnboxedOk _ = IfUnboxedOk
+combine _ IfUnboxedOk = IfUnboxedOk
+combine _ _ = OkToSpec
+
+instance Outputable FloatingBind where
+ ppr (FloatLet bind) = text "FloatLet" <+> ppr bind
+ ppr (FloatCase b rhs spec) = text "FloatCase" <+> ppr b <+> ppr spec <+> equals <+> ppr rhs
+
+deFloatTop :: Floats -> [CoreBind]
+-- For top level only; we don't expect any FloatCases
+deFloatTop (Floats _ floats)
+ = foldrOL get [] floats
+ where
+ get (FloatLet b) bs = b:bs
+ get b bs = pprPanic "corePrepPgm" (ppr b)
+
+allLazy :: TopLevelFlag -> RecFlag -> Floats -> Bool
+allLazy top_lvl is_rec (Floats ok_to_spec _)
+ = case ok_to_spec of
+ OkToSpec -> True
+ NotOkToSpec -> False
+ IfUnboxedOk -> isNotTopLevel top_lvl && isNonRec is_rec
+
+-- ---------------------------------------------------------------------------
+-- Bindings
+-- ---------------------------------------------------------------------------
+
+corePrepTopBinds :: [CoreBind] -> UniqSM Floats
+corePrepTopBinds binds
+ = go emptyCorePrepEnv binds
+ where
+ go env [] = returnUs emptyFloats
+ go env (bind : binds) = corePrepTopBind env bind `thenUs` \ (env', bind') ->
+ go env' binds `thenUs` \ binds' ->
+ returnUs (bind' `appendFloats` binds')
+
+-- NB: we do need to float out of top-level bindings
+-- Consider x = length [True,False]
+-- We want to get
+-- s1 = False : []
+-- s2 = True : s1
+-- x = length s2
+
+-- We return a *list* of bindings, because we may start with
+-- x* = f (g y)
+-- where x is demanded, in which case we want to finish with
+-- a = g y
+-- x* = f a
+-- And then x will actually end up case-bound
+--
+-- What happens to the CafInfo on the floated bindings? By
+-- default, all the CafInfos will be set to MayHaveCafRefs,
+-- which is safe.
+--
+-- This might be pessimistic, because eg. s1 & s2
+-- might not refer to any CAFs and the GC will end up doing
+-- more traversal than is necessary, but it's still better
+-- than not floating the bindings at all, because then
+-- the GC would have to traverse the structure in the heap
+-- instead. Given this, we decided not to try to get
+-- the CafInfo on the floated bindings correct, because
+-- it looks difficult.
+
+--------------------------------
+corePrepTopBind :: CorePrepEnv -> CoreBind -> UniqSM (CorePrepEnv, Floats)
+corePrepTopBind env (NonRec bndr rhs)
+ = cloneBndr env bndr `thenUs` \ (env', bndr') ->
+ corePrepRhs TopLevel NonRecursive env (bndr, rhs) `thenUs` \ (floats, rhs') ->
+ returnUs (env', addFloat floats (FloatLet (NonRec bndr' rhs')))
+
+corePrepTopBind env (Rec pairs) = corePrepRecPairs TopLevel env pairs
+
+--------------------------------
+corePrepBind :: CorePrepEnv -> CoreBind -> UniqSM (CorePrepEnv, Floats)
+ -- This one is used for *local* bindings
+corePrepBind env (NonRec bndr rhs)
+ = etaExpandRhs bndr rhs `thenUs` \ rhs1 ->
+ corePrepExprFloat env rhs1 `thenUs` \ (floats, rhs2) ->
+ cloneBndr env bndr `thenUs` \ (_, bndr') ->
+ mkLocalNonRec bndr' (bdrDem bndr) floats rhs2 `thenUs` \ (floats', bndr'') ->
+ -- We want bndr'' in the envt, because it records
+ -- the evaluated-ness of the binder
+ returnUs (extendCorePrepEnv env bndr bndr'', floats')
+
+corePrepBind env (Rec pairs) = corePrepRecPairs NotTopLevel env pairs
+
+--------------------------------
+corePrepRecPairs :: TopLevelFlag -> CorePrepEnv
+ -> [(Id,CoreExpr)] -- Recursive bindings
+ -> UniqSM (CorePrepEnv, Floats)
+-- Used for all recursive bindings, top level and otherwise
+corePrepRecPairs lvl env pairs
+ = cloneBndrs env (map fst pairs) `thenUs` \ (env', bndrs') ->
+ mapAndUnzipUs (corePrepRhs lvl Recursive env') pairs `thenUs` \ (floats_s, rhss') ->
+ returnUs (env', unitFloat (FloatLet (Rec (flatten (concatFloats floats_s) bndrs' rhss'))))
+ where
+ -- Flatten all the floats, and the currrent
+ -- group into a single giant Rec
+ flatten (Floats _ floats) bndrs rhss = foldrOL get (bndrs `zip` rhss) floats
+
+ get (FloatLet (NonRec b r)) prs2 = (b,r) : prs2
+ get (FloatLet (Rec prs1)) prs2 = prs1 ++ prs2
+ get b prs2 = pprPanic "corePrepRecPairs" (ppr b)
+
+--------------------------------
+corePrepRhs :: TopLevelFlag -> RecFlag
+ -> CorePrepEnv -> (Id, CoreExpr)
+ -> UniqSM (Floats, CoreExpr)
+-- Used for top-level bindings, and local recursive bindings
+corePrepRhs top_lvl is_rec env (bndr, rhs)
+ = etaExpandRhs bndr rhs `thenUs` \ rhs' ->
+ corePrepExprFloat env rhs' `thenUs` \ floats_w_rhs ->
+ floatRhs top_lvl is_rec bndr floats_w_rhs
+
+
+-- ---------------------------------------------------------------------------
+-- Making arguments atomic (function args & constructor args)
+-- ---------------------------------------------------------------------------
+
+-- This is where we arrange that a non-trivial argument is let-bound
+corePrepArg :: CorePrepEnv -> CoreArg -> RhsDemand
+ -> UniqSM (Floats, CoreArg)
+corePrepArg env arg dem
+ = corePrepExprFloat env arg `thenUs` \ (floats, arg') ->
+ if exprIsTrivial arg'
+ then returnUs (floats, arg')
+ else newVar (exprType arg') `thenUs` \ v ->
+ mkLocalNonRec v dem floats arg' `thenUs` \ (floats', v') ->
+ returnUs (floats', Var v')
+
+-- version that doesn't consider an scc annotation to be trivial.
+exprIsTrivial (Var v) = True
+exprIsTrivial (Type _) = True
+exprIsTrivial (Lit lit) = True
+exprIsTrivial (App e arg) = isTypeArg arg && exprIsTrivial e
+exprIsTrivial (Note (SCC _) e) = False
+exprIsTrivial (Note _ e) = exprIsTrivial e
+exprIsTrivial (Lam b body) | isTyVar b = exprIsTrivial body
+exprIsTrivial other = False
+
+-- ---------------------------------------------------------------------------
+-- Dealing with expressions
+-- ---------------------------------------------------------------------------
+
+corePrepAnExpr :: CorePrepEnv -> CoreExpr -> UniqSM CoreExpr
+corePrepAnExpr env expr
+ = corePrepExprFloat env expr `thenUs` \ (floats, expr) ->
+ mkBinds floats expr
+
+
+corePrepExprFloat :: CorePrepEnv -> CoreExpr -> UniqSM (Floats, CoreExpr)
+-- If
+-- e ===> (bs, e')
+-- then
+-- e = let bs in e' (semantically, that is!)
+--
+-- For example
+-- f (g x) ===> ([v = g x], f v)
+
+corePrepExprFloat env (Var v)
+ = fiddleCCall v `thenUs` \ v1 ->
+ let
+ v2 = lookupCorePrepEnv env v1
+ in
+ maybeSaturate v2 (Var v2) 0 emptyFloats (idType v2)
+
+corePrepExprFloat env expr@(Type _)
+ = returnUs (emptyFloats, expr)
+
+corePrepExprFloat env expr@(Lit lit)
+ = returnUs (emptyFloats, expr)
+
+corePrepExprFloat env (Let bind body)
+ = corePrepBind env bind `thenUs` \ (env', new_binds) ->
+ corePrepExprFloat env' body `thenUs` \ (floats, new_body) ->
+ returnUs (new_binds `appendFloats` floats, new_body)
+
+corePrepExprFloat env (Note n@(SCC _) expr)
+ = corePrepAnExpr env expr `thenUs` \ expr1 ->
+ deLamFloat expr1 `thenUs` \ (floats, expr2) ->
+ returnUs (floats, Note n expr2)
+
+corePrepExprFloat env (Note other_note expr)
+ = corePrepExprFloat env expr `thenUs` \ (floats, expr') ->
+ returnUs (floats, Note other_note expr')
+
+corePrepExprFloat env expr@(Lam _ _)
+ = cloneBndrs env bndrs `thenUs` \ (env', bndrs') ->
+ corePrepAnExpr env' body `thenUs` \ body' ->
+ returnUs (emptyFloats, mkLams bndrs' body')
+ where
+ (bndrs,body) = collectBinders expr
+
+corePrepExprFloat env (Case scrut bndr ty alts)
+ = corePrepExprFloat env scrut `thenUs` \ (floats1, scrut1) ->
+ deLamFloat scrut1 `thenUs` \ (floats2, scrut2) ->
+ let
+ bndr1 = bndr `setIdUnfolding` evaldUnfolding
+ -- Record that the case binder is evaluated in the alternatives
+ in
+ cloneBndr env bndr1 `thenUs` \ (env', bndr2) ->
+ mapUs (sat_alt env') alts `thenUs` \ alts' ->
+ returnUs (floats1 `appendFloats` floats2 , Case scrut2 bndr2 ty alts')
+ where
+ sat_alt env (con, bs, rhs)
+ = let
+ env1 = setGadt env con
+ in
+ cloneBndrs env1 bs `thenUs` \ (env2, bs') ->
+ corePrepAnExpr env2 rhs `thenUs` \ rhs1 ->
+ deLam rhs1 `thenUs` \ rhs2 ->
+ returnUs (con, bs', rhs2)
+
+corePrepExprFloat env expr@(App _ _)
+ = collect_args expr 0 `thenUs` \ (app, (head,depth), ty, floats, ss) ->
+ ASSERT(null ss) -- make sure we used all the strictness info
+
+ -- Now deal with the function
+ case head of
+ Var fn_id -> maybeSaturate fn_id app depth floats ty
+ _other -> returnUs (floats, app)
+
+ where
+
+ -- Deconstruct and rebuild the application, floating any non-atomic
+ -- arguments to the outside. We collect the type of the expression,
+ -- the head of the application, and the number of actual value arguments,
+ -- all of which are used to possibly saturate this application if it
+ -- has a constructor or primop at the head.
+
+ collect_args
+ :: CoreExpr
+ -> Int -- current app depth
+ -> UniqSM (CoreExpr, -- the rebuilt expression
+ (CoreExpr,Int), -- the head of the application,
+ -- and no. of args it was applied to
+ Type, -- type of the whole expr
+ Floats, -- any floats we pulled out
+ [Demand]) -- remaining argument demands
+
+ collect_args (App fun arg@(Type arg_ty)) depth
+ = collect_args fun depth `thenUs` \ (fun',hd,fun_ty,floats,ss) ->
+ returnUs (App fun' arg, hd, applyTy fun_ty arg_ty, floats, ss)
+
+ collect_args (App fun arg) depth
+ = collect_args fun (depth+1) `thenUs` \ (fun',hd,fun_ty,floats,ss) ->
+ let
+ (ss1, ss_rest) = case ss of
+ (ss1:ss_rest) -> (ss1, ss_rest)
+ [] -> (lazyDmd, [])
+ (arg_ty, res_ty) = expectJust "corePrepExprFloat:collect_args" $
+ splitFunTy_maybe fun_ty
+ in
+ corePrepArg env arg (mkDemTy ss1 arg_ty) `thenUs` \ (fs, arg') ->
+ returnUs (App fun' arg', hd, res_ty, fs `appendFloats` floats, ss_rest)
+
+ collect_args (Var v) depth
+ = fiddleCCall v `thenUs` \ v1 ->
+ let
+ v2 = lookupCorePrepEnv env v1
+ in
+ returnUs (Var v2, (Var v2, depth), idType v2, emptyFloats, stricts)
+ where
+ stricts = case idNewStrictness v of
+ StrictSig (DmdType _ demands _)
+ | listLengthCmp demands depth /= GT -> demands
+ -- length demands <= depth
+ | otherwise -> []
+ -- If depth < length demands, then we have too few args to
+ -- satisfy strictness info so we have to ignore all the
+ -- strictness info, e.g. + (error "urk")
+ -- Here, we can't evaluate the arg strictly, because this
+ -- partial application might be seq'd
+
+
+ collect_args (Note (Coerce ty1 ty2) fun) depth
+ = collect_args fun depth `thenUs` \ (fun', hd, fun_ty, floats, ss) ->
+ returnUs (Note (Coerce ty1 ty2) fun', hd, ty1, floats, ss)
+
+ collect_args (Note note fun) depth
+ | ignore_note note -- Drop these notes altogether
+ -- They aren't used by the code generator
+ = collect_args fun depth `thenUs` \ (fun', hd, fun_ty, floats, ss) ->
+ returnUs (fun', hd, fun_ty, floats, ss)
+
+ -- N-variable fun, better let-bind it
+ -- ToDo: perhaps we can case-bind rather than let-bind this closure,
+ -- since it is sure to be evaluated.
+ collect_args fun depth
+ = corePrepExprFloat env fun `thenUs` \ (fun_floats, fun') ->
+ newVar ty `thenUs` \ fn_id ->
+ mkLocalNonRec fn_id onceDem fun_floats fun' `thenUs` \ (floats, fn_id') ->
+ returnUs (Var fn_id', (Var fn_id', depth), ty, floats, [])
+ where
+ ty = exprType fun
+
+ ignore_note (CoreNote _) = True
+ ignore_note InlineCall = True
+ ignore_note InlineMe = True
+ ignore_note _other = False
+ -- We don't ignore SCCs, since they require some code generation
+
+------------------------------------------------------------------------------
+-- Building the saturated syntax
+-- ---------------------------------------------------------------------------
+
+-- maybeSaturate deals with saturating primops and constructors
+-- The type is the type of the entire application
+maybeSaturate :: Id -> CoreExpr -> Int -> Floats -> Type -> UniqSM (Floats, CoreExpr)
+maybeSaturate fn expr n_args floats ty
+ | Just DataToTagOp <- isPrimOpId_maybe fn -- DataToTag must have an evaluated arg
+ -- A gruesome special case
+ = saturate_it `thenUs` \ sat_expr ->
+
+ -- OK, now ensure that the arg is evaluated.
+ -- But (sigh) take into account the lambdas we've now introduced
+ let
+ (eta_bndrs, eta_body) = collectBinders sat_expr
+ in
+ eval_data2tag_arg eta_body `thenUs` \ (eta_floats, eta_body') ->
+ if null eta_bndrs then
+ returnUs (floats `appendFloats` eta_floats, eta_body')
+ else
+ mkBinds eta_floats eta_body' `thenUs` \ eta_body'' ->
+ returnUs (floats, mkLams eta_bndrs eta_body'')
+
+ | hasNoBinding fn = saturate_it `thenUs` \ sat_expr ->
+ returnUs (floats, sat_expr)
+
+ | otherwise = returnUs (floats, expr)
+
+ where
+ fn_arity = idArity fn
+ excess_arity = fn_arity - n_args
+
+ saturate_it :: UniqSM CoreExpr
+ saturate_it | excess_arity == 0 = returnUs expr
+ | otherwise = getUniquesUs `thenUs` \ us ->
+ returnUs (etaExpand excess_arity us expr ty)
+
+ -- Ensure that the argument of DataToTagOp is evaluated
+ eval_data2tag_arg :: CoreExpr -> UniqSM (Floats, CoreExpr)
+ eval_data2tag_arg app@(fun `App` arg)
+ | exprIsHNF arg -- Includes nullary constructors
+ = returnUs (emptyFloats, app) -- The arg is evaluated
+ | otherwise -- Arg not evaluated, so evaluate it
+ = newVar (exprType arg) `thenUs` \ arg_id ->
+ let
+ arg_id1 = setIdUnfolding arg_id evaldUnfolding
+ in
+ returnUs (unitFloat (FloatCase arg_id1 arg False ),
+ fun `App` Var arg_id1)
+
+ eval_data2tag_arg (Note note app) -- Scc notes can appear
+ = eval_data2tag_arg app `thenUs` \ (floats, app') ->
+ returnUs (floats, Note note app')
+
+ eval_data2tag_arg other -- Should not happen
+ = pprPanic "eval_data2tag" (ppr other)
+
+
+-- ---------------------------------------------------------------------------
+-- Precipitating the floating bindings
+-- ---------------------------------------------------------------------------
+
+floatRhs :: TopLevelFlag -> RecFlag
+ -> Id
+ -> (Floats, CoreExpr) -- Rhs: let binds in body
+ -> UniqSM (Floats, -- Floats out of this bind
+ CoreExpr) -- Final Rhs
+
+floatRhs top_lvl is_rec bndr (floats, rhs)
+ | isTopLevel top_lvl || exprIsHNF rhs, -- Float to expose value or
+ allLazy top_lvl is_rec floats -- at top level
+ = -- Why the test for allLazy?
+ -- v = f (x `divInt#` y)
+ -- we don't want to float the case, even if f has arity 2,
+ -- because floating the case would make it evaluated too early
+ returnUs (floats, rhs)
+
+ | otherwise
+ -- Don't float; the RHS isn't a value
+ = mkBinds floats rhs `thenUs` \ rhs' ->
+ returnUs (emptyFloats, rhs')
+
+-- mkLocalNonRec is used only for *nested*, *non-recursive* bindings
+mkLocalNonRec :: Id -> RhsDemand -- Lhs: id with demand
+ -> Floats -> CoreExpr -- Rhs: let binds in body
+ -> UniqSM (Floats, Id) -- The new Id may have an evaldUnfolding,
+ -- to record that it's been evaluated
+
+mkLocalNonRec bndr dem floats rhs
+ | isUnLiftedType (idType bndr)
+ -- If this is an unlifted binding, we always make a case for it.
+ = ASSERT( not (isUnboxedTupleType (idType bndr)) )
+ let
+ float = FloatCase bndr rhs (exprOkForSpeculation rhs)
+ in
+ returnUs (addFloat floats float, evald_bndr)
+
+ | isStrict dem
+ -- It's a strict let so we definitely float all the bindings
+ = let -- Don't make a case for a value binding,
+ -- even if it's strict. Otherwise we get
+ -- case (\x -> e) of ...!
+ float | exprIsHNF rhs = FloatLet (NonRec bndr rhs)
+ | otherwise = FloatCase bndr rhs (exprOkForSpeculation rhs)
+ in
+ returnUs (addFloat floats float, evald_bndr)
+
+ | otherwise
+ = floatRhs NotTopLevel NonRecursive bndr (floats, rhs) `thenUs` \ (floats', rhs') ->
+ returnUs (addFloat floats' (FloatLet (NonRec bndr rhs')),
+ if exprIsHNF rhs' then evald_bndr else bndr)
+
+ where
+ evald_bndr = bndr `setIdUnfolding` evaldUnfolding
+ -- Record if the binder is evaluated
+
+
+mkBinds :: Floats -> CoreExpr -> UniqSM CoreExpr
+mkBinds (Floats _ binds) body
+ | isNilOL binds = returnUs body
+ | otherwise = deLam body `thenUs` \ body' ->
+ -- Lambdas are not allowed as the body of a 'let'
+ returnUs (foldrOL mk_bind body' binds)
+ where
+ mk_bind (FloatCase bndr rhs _) body = Case rhs bndr (exprType body) [(DEFAULT, [], body)]
+ mk_bind (FloatLet bind) body = Let bind body
+
+etaExpandRhs bndr rhs
+ = -- Eta expand to match the arity claimed by the binder
+ -- Remember, after CorePrep we must not change arity
+ --
+ -- Eta expansion might not have happened already,
+ -- because it is done by the simplifier only when
+ -- there at least one lambda already.
+ --
+ -- NB1:we could refrain when the RHS is trivial (which can happen
+ -- for exported things). This would reduce the amount of code
+ -- generated (a little) and make things a little words for
+ -- code compiled without -O. The case in point is data constructor
+ -- wrappers.
+ --
+ -- NB2: we have to be careful that the result of etaExpand doesn't
+ -- invalidate any of the assumptions that CorePrep is attempting
+ -- to establish. One possible cause is eta expanding inside of
+ -- an SCC note - we're now careful in etaExpand to make sure the
+ -- SCC is pushed inside any new lambdas that are generated.
+ --
+ -- NB3: It's important to do eta expansion, and *then* ANF-ising
+ -- f = /\a -> g (h 3) -- h has arity 2
+ -- If we ANF first we get
+ -- f = /\a -> let s = h 3 in g s
+ -- and now eta expansion gives
+ -- f = /\a -> \ y -> (let s = h 3 in g s) y
+ -- which is horrible.
+ -- Eta expanding first gives
+ -- f = /\a -> \y -> let s = h 3 in g s y
+ --
+ getUniquesUs `thenUs` \ us ->
+ returnUs (etaExpand arity us rhs (idType bndr))
+ where
+ -- For a GlobalId, take the Arity from the Id.
+ -- It was set in CoreTidy and must not change
+ -- For all others, just expand at will
+ arity | isGlobalId bndr = idArity bndr
+ | otherwise = exprArity rhs
+
+-- ---------------------------------------------------------------------------
+-- Eliminate Lam as a non-rhs (STG doesn't have such a thing)
+-- We arrange that they only show up as the RHS of a let(rec)
+-- ---------------------------------------------------------------------------
+
+deLam :: CoreExpr -> UniqSM CoreExpr
+deLam expr =
+ deLamFloat expr `thenUs` \ (floats, expr) ->
+ mkBinds floats expr
+
+
+deLamFloat :: CoreExpr -> UniqSM (Floats, CoreExpr)
+-- Remove top level lambdas by let-bindinig
+
+deLamFloat (Note n expr)
+ = -- You can get things like
+ -- case e of { p -> coerce t (\s -> ...) }
+ deLamFloat expr `thenUs` \ (floats, expr') ->
+ returnUs (floats, Note n expr')
+
+deLamFloat expr
+ | null bndrs = returnUs (emptyFloats, expr)
+ | otherwise
+ = case tryEta bndrs body of
+ Just no_lam_result -> returnUs (emptyFloats, no_lam_result)
+ Nothing -> newVar (exprType expr) `thenUs` \ fn ->
+ returnUs (unitFloat (FloatLet (NonRec fn expr)),
+ Var fn)
+ where
+ (bndrs,body) = collectBinders expr
+
+-- Why try eta reduction? Hasn't the simplifier already done eta?
+-- But the simplifier only eta reduces if that leaves something
+-- trivial (like f, or f Int). But for deLam it would be enough to
+-- get to a partial application, like (map f).
+
+tryEta bndrs expr@(App _ _)
+ | ok_to_eta_reduce f &&
+ n_remaining >= 0 &&
+ and (zipWith ok bndrs last_args) &&
+ not (any (`elemVarSet` fvs_remaining) bndrs)
+ = Just remaining_expr
+ where
+ (f, args) = collectArgs expr
+ remaining_expr = mkApps f remaining_args
+ fvs_remaining = exprFreeVars remaining_expr
+ (remaining_args, last_args) = splitAt n_remaining args
+ n_remaining = length args - length bndrs
+
+ ok bndr (Var arg) = bndr == arg
+ ok bndr other = False
+
+ -- we can't eta reduce something which must be saturated.
+ ok_to_eta_reduce (Var f) = not (hasNoBinding f)
+ ok_to_eta_reduce _ = False --safe. ToDo: generalise
+
+tryEta bndrs (Let bind@(NonRec b r) body)
+ | not (any (`elemVarSet` fvs) bndrs)
+ = case tryEta bndrs body of
+ Just e -> Just (Let bind e)
+ Nothing -> Nothing
+ where
+ fvs = exprFreeVars r
+
+tryEta bndrs _ = Nothing
+\end{code}
+
+
+-- -----------------------------------------------------------------------------
+-- Demands
+-- -----------------------------------------------------------------------------
+
+\begin{code}
+data RhsDemand
+ = RhsDemand { isStrict :: Bool, -- True => used at least once
+ isOnceDem :: Bool -- True => used at most once
+ }
+
+mkDem :: Demand -> Bool -> RhsDemand
+mkDem strict once = RhsDemand (isStrictDmd strict) once
+
+mkDemTy :: Demand -> Type -> RhsDemand
+mkDemTy strict ty = RhsDemand (isStrictDmd strict)
+ False {- For now -}
+
+bdrDem :: Id -> RhsDemand
+bdrDem id = mkDem (idNewDemandInfo id)
+ False {- For now -}
+
+-- safeDem :: RhsDemand
+-- safeDem = RhsDemand False False -- always safe to use this
+
+onceDem :: RhsDemand
+onceDem = RhsDemand False True -- used at most once
+\end{code}
+
+
+
+
+%************************************************************************
+%* *
+\subsection{Cloning}
+%* *
+%************************************************************************
+
+\begin{code}
+-- ---------------------------------------------------------------------------
+-- The environment
+-- ---------------------------------------------------------------------------
+
+data CorePrepEnv = CPE (IdEnv Id) -- Clone local Ids
+ Bool -- True <=> inside a GADT case; see Note [GADT]
+
+-- Note [GADT]
+--
+-- Be careful with cloning inside GADTs. For example,
+-- /\a. \f::a. \x::T a. case x of { T -> f True; ... }
+-- The case on x may refine the type of f to be a function type.
+-- Without this type refinement, exprType (f True) may simply fail,
+-- which is bad.
+--
+-- Solution: remember when we are inside a potentially-type-refining case,
+-- and in that situation use the type from the old occurrence
+-- when looking up occurrences
+
+emptyCorePrepEnv :: CorePrepEnv
+emptyCorePrepEnv = CPE emptyVarEnv False
+
+extendCorePrepEnv :: CorePrepEnv -> Id -> Id -> CorePrepEnv
+extendCorePrepEnv (CPE env gadt) id id' = CPE (extendVarEnv env id id') gadt
+
+lookupCorePrepEnv :: CorePrepEnv -> Id -> Id
+-- See Note [GADT] above
+lookupCorePrepEnv (CPE env gadt) id
+ = case lookupVarEnv env id of
+ Nothing -> id
+ Just id' | gadt -> setIdType id' (idType id)
+ | otherwise -> id'
+
+setGadt :: CorePrepEnv -> AltCon -> CorePrepEnv
+setGadt env@(CPE id_env _) (DataAlt data_con) | not (isVanillaDataCon data_con) = CPE id_env True
+setGadt env other = env
+
+
+------------------------------------------------------------------------------
+-- Cloning binders
+-- ---------------------------------------------------------------------------
+
+cloneBndrs :: CorePrepEnv -> [Var] -> UniqSM (CorePrepEnv, [Var])
+cloneBndrs env bs = mapAccumLUs cloneBndr env bs
+
+cloneBndr :: CorePrepEnv -> Var -> UniqSM (CorePrepEnv, Var)
+cloneBndr env bndr
+ | isLocalId bndr
+ = getUniqueUs `thenUs` \ uniq ->
+ let
+ bndr' = setVarUnique bndr uniq
+ in
+ returnUs (extendCorePrepEnv env bndr bndr', bndr')
+
+ | otherwise -- Top level things, which we don't want
+ -- to clone, have become GlobalIds by now
+ -- And we don't clone tyvars
+ = returnUs (env, bndr)
+
+
+------------------------------------------------------------------------------
+-- Cloning ccall Ids; each must have a unique name,
+-- to give the code generator a handle to hang it on
+-- ---------------------------------------------------------------------------
+
+fiddleCCall :: Id -> UniqSM Id
+fiddleCCall id
+ | isFCallId id = getUniqueUs `thenUs` \ uniq ->
+ returnUs (id `setVarUnique` uniq)
+ | otherwise = returnUs id
+
+------------------------------------------------------------------------------
+-- Generating new binders
+-- ---------------------------------------------------------------------------
+
+newVar :: Type -> UniqSM Id
+newVar ty
+ = seqType ty `seq`
+ getUniqueUs `thenUs` \ uniq ->
+ returnUs (mkSysLocal FSLIT("sat") uniq ty)
+\end{code}