import Const ( Con(..) )
import PrimRep ( PrimRep )
import PrimOp ( PrimOp )
+import TysPrim ( realWorldStatePrimTy )
import FieldLabel ( FieldLabel(..) )
import SrcLoc ( SrcLoc )
import Unique ( Unique, mkBuiltinUnique, getBuiltinUniques )
isOneShotLambda :: Id -> Bool
isOneShotLambda id = case lbvarInfo (idInfo id) of
IsOneShotLambda -> True
- NoLBVarInfo -> False
+ NoLBVarInfo -> idType id == realWorldStatePrimTy
+ -- The last clause is a gross hack. It claims that
+ -- every function over realWorldStatePrimTy is a one-shot
+ -- function. This is pretty true in practice, and makes a big
+ -- difference. For example, consider
+ -- a `thenST` \ r -> ...E...
+ -- The early full laziness pass, if it doesn't know that r is one-shot
+ -- will pull out E (let's say it doesn't mention r) to give
+ -- let lvl = E in a `thenST` \ r -> ...lvl...
+ -- When `thenST` gets inlined, we end up with
+ -- let lvl = E in \s -> case a s of (r, s') -> ...lvl...
+ -- and we don't re-inline E.
+ --
+ -- It would be better to spot that r was one-shot to start with, but
+ -- I don't want to rely on that.
setOneShotLambda :: Id -> Id
setOneShotLambda id = modifyIdInfo (`setLBVarInfo` IsOneShotLambda) id
-- Arity
ArityInfo(..),
- exactArity, atLeastArity, unknownArity,
+ exactArity, atLeastArity, unknownArity, hasArity,
arityInfo, setArityInfo, ppArityInfo, arityLowerBound,
-- Strictness
-- Worker
WorkerInfo, workerExists,
- workerInfo, setWorkerInfo,
+ workerInfo, setWorkerInfo, ppWorkerInfo,
-- Unfolding
unfoldingInfo, setUnfoldingInfo,
arityLowerBound (ArityAtLeast n) = n
arityLowerBound (ArityExactly n) = n
+hasArity :: ArityInfo -> Bool
+hasArity UnknownArity = False
+hasArity other = True
ppArityInfo UnknownArity = empty
ppArityInfo (ArityExactly arity) = hsep [ptext SLIT("__A"), int arity]
{- UNUSED:
mkWorkerInfo :: Id -> WorkerInfo
mkWorkerInfo wk_id = Just wk_id
+-}
ppWorkerInfo Nothing = empty
-ppWorkerInfo (Just wk_id) = ppr wk_id
--}
+ppWorkerInfo (Just wk_id) = ptext SLIT("__P") <+> ppr wk_id
noWorkerInfo = Nothing
\begin{code}
zapFragileIdInfo :: IdInfo -> Maybe IdInfo
zapFragileIdInfo info@(IdInfo {inlinePragInfo = inline_prag,
+ workerInfo = wrkr,
specInfo = rules,
unfoldingInfo = unfolding})
| not is_fragile_inline_prag
-- Specialisations would need substituting. They get pinned
-- back on separately.
+ && not (workerExists wrkr)
+
&& not (hasUnfolding unfolding)
-- This is very important; occasionally a let-bound binder is used
-- as a binder in some lambda, in which case its unfolding is utterly
| otherwise
= Just (info {inlinePragInfo = safe_inline_prag,
+ workerInfo = noWorkerInfo,
specInfo = emptyCoreRules,
unfoldingInfo = noUnfolding})
TaggedExpr, TaggedAlt, TaggedBind, TaggedArg,
mkLets, mkLams,
- mkApps, mkTyApps, mkValApps,
+ mkApps, mkTyApps, mkValApps, mkVarApps,
mkLit, mkStringLit, mkConApp, mkPrimApp, mkNote,
bindNonRec, mkIfThenElse, varToCoreExpr,
mkApps :: Expr b -> [Arg b] -> Expr b
mkTyApps :: Expr b -> [Type] -> Expr b
mkValApps :: Expr b -> [Expr b] -> Expr b
+mkVarApps :: CoreExpr -> [IdOrTyVar] -> CoreExpr
mkApps f args = foldl App f args
mkTyApps f args = foldl (\ e a -> App e (Type a)) f args
mkValApps f args = foldl (\ e a -> App e a) f args
+mkVarApps f vars = foldl (\ e a -> App e (varToCoreExpr a)) f vars
mkLit :: Literal -> Expr b
mkStringLit :: String -> Expr b
)
import IdInfo ( specInfo, setSpecInfo,
inlinePragInfo, setInlinePragInfo, InlinePragInfo(..),
- setUnfoldingInfo, setDemandInfo
+ setUnfoldingInfo, setDemandInfo,
+ workerInfo, setWorkerInfo
)
import Demand ( wwLazy )
import Name ( getOccName, tidyTopName, mkLocalName, isLocallyDefined )
-> (TidyEnv, CoreBind)
tidyBind maybe_mod env (NonRec bndr rhs)
= let
- (env', bndr') = tidy_bndr maybe_mod env bndr
+ (env', bndr') = tidy_bndr maybe_mod env env bndr
rhs' = tidyExpr env rhs
in
(env', NonRec bndr' rhs')
-- So I left it out for now
(bndrs, rhss) = unzip pairs
- (env', bndrs') = mapAccumL (tidy_bndr maybe_mod) env bndrs
+ (env', bndrs') = mapAccumL (tidy_bndr maybe_mod env') env bndrs
rhss' = map (tidyExpr env') rhss
in
(env', Rec (zip bndrs' rhss'))
\end{code}
\begin{code}
-tidy_bndr (Just mod) env id = tidyTopId mod env id
-tidy_bndr Nothing env var = tidyBndr env var
+tidy_bndr (Just mod) env_idinfo env var = tidyTopId mod env env_idinfo var
+tidy_bndr Nothing env_idinfo env var = tidyBndr env var
\end{code}
in
((tidy_env', var_env'), id')
-tidyTopId :: Module -> TidyEnv -> Id -> (TidyEnv, Id)
-tidyTopId mod env@(tidy_env, var_env) id
+tidyTopId :: Module -> TidyEnv -> TidyEnv -> Id -> (TidyEnv, Id)
+ -- The second env is the one to use for the IdInfo
+ -- It's necessary because when we are dealing with a recursive
+ -- group, a variable late in the group might be mentioned
+ -- in the IdInfo of one early in the group
+tidyTopId mod env@(tidy_env, var_env) env_idinfo id
= -- Top level variables
let
(tidy_env', name') | isUserExportedId id = (tidy_env, idName id)
| otherwise = tidyTopName mod tidy_env (idName id)
ty' = tidyTopType (idType id)
- idinfo' = tidyIdInfo env (idInfo id)
+ idinfo' = tidyIdInfo env_idinfo (idInfo id)
id' = mkId name' ty' idinfo'
var_env' = extendVarEnv var_env id id'
in
-- The latter two are to avoid space leaks
tidyIdInfo env info
- = info4
+ = info5
where
rules = specInfo info
info3 = info2 `setUnfoldingInfo` noUnfolding
info4 = info3 `setDemandInfo` wwLazy -- I don't understand why...
+ info5 = case workerInfo info of
+ Nothing -> info4
+ Just w -> info4 `setWorkerInfo` Just (tidyVarOcc env w)
+
tidyProtoRules :: TidyEnv -> [ProtoCoreRule] -> [ProtoCoreRule]
tidyProtoRules env rules
= [ ProtoCoreRule is_local (tidyVarOcc env fn) (tidyRule env rule)
mkOtherCon, otherCons,
unfoldingTemplate, maybeUnfoldingTemplate,
isEvaldUnfolding, isCheapUnfolding,
- hasUnfolding,
+ hasUnfolding, hasSomeUnfolding,
couldBeSmallEnoughToInline,
certainlySmallEnoughToInline,
callSiteInline :: Bool -- True <=> the Id is black listed
-> Bool -- 'inline' note at call site
-> Id -- The Id
- -> [CoreExpr] -- Arguments
+ -> [Bool] -- One for each value arg; True if it is interesting
-> Bool -- True <=> continuation is interesting
-> Maybe CoreExpr -- Unfolding, if any
-callSiteInline black_listed inline_call id args interesting_cont
+callSiteInline black_listed inline_call id arg_infos interesting_cont
= case getIdUnfolding id of {
NoUnfolding -> Nothing ;
OtherCon _ -> Nothing ;
| otherwise = Nothing
inline_prag = getInlinePragma id
- arg_infos = map interestingArg val_args
- val_args = filter isValArg args
+ n_val_args = length arg_infos
yes_or_no =
case inline_prag of
text "callSiteInline:oneOcc" <+> ppr id )
-- If it has one occurrence, not inside a lambda, PreInlineUnconditionally
-- should have zapped it already
- is_cheap && (not (null args) || interesting_cont)
+ is_cheap && (not (null arg_infos) || interesting_cont)
| otherwise -- Occurs (textually) more than once, so look at its size
= case guidance of
InsideLam -> is_cheap && small_enough
where
- n_args = length arg_infos
- enough_args = n_args >= n_vals_wanted
- really_interesting_cont | n_args < n_vals_wanted = False -- Too few args
- | n_args == n_vals_wanted = interesting_cont
- | otherwise = True -- Extra args
+ enough_args = n_val_args >= n_vals_wanted
+ really_interesting_cont | n_val_args < n_vals_wanted = False -- Too few args
+ | n_val_args == n_vals_wanted = interesting_cont
+ | otherwise = True -- Extra args
-- This rather elaborate defn for really_interesting_cont is important
-- Consider an I# = INLINE (\x -> I# {x})
-- The unfolding guidance deems it to have size 2, and no arguments.
result
}
--- An argument is interesting if it has *some* structure
--- We are here trying to avoid unfolding a function that
--- is applied only to variables that have no unfolding
--- (i.e. they are probably lambda bound): f x y z
--- There is little point in inlining f here.
-interestingArg (Type _) = False
-interestingArg (App fn (Type _)) = interestingArg fn
-interestingArg (Var v) = hasSomeUnfolding (getIdUnfolding v)
-interestingArg other = True
-
-
computeDiscount :: Int -> [Int] -> Int -> [Bool] -> Bool -> Int
computeDiscount n_vals_wanted arg_discounts res_discount arg_infos result_used
-- We multiple the raw discounts (args_discount and result_discount)
module CoreUtils (
coreExprType, coreAltsType,
- exprIsBottom, exprIsDupable, exprIsTrivial, exprIsCheap, exprIsValue,
+ exprIsBottom, exprIsDupable, exprIsTrivial, exprIsCheap,
+ exprIsValue,
exprOkForSpeculation, exprIsBig, hashExpr,
- exprArity,
+ exprArity, exprGenerousArity,
cheapEqExpr, eqExpr, applyTypeToArgs
) where
exprIsCheap (Con con args) = conIsCheap con && all exprIsCheap args
exprIsCheap (Note _ e) = exprIsCheap e
exprIsCheap (Lam x e) = if isId x then True else exprIsCheap e
-
--- I'm not at all convinced about these two!!
--- [SLPJ June 99]
--- exprIsCheap (Let bind body) = all exprIsCheap (rhssOfBind bind) && exprIsCheap body
--- exprIsCheap (Case scrut _ alts) = exprIsCheap scrut &&
--- all (\(_,_,rhs) -> exprIsCheap rhs) alts
-
exprIsCheap other_expr -- look for manifest partial application
= case collectArgs other_expr of
(f, args) -> isPap f (valArgCount args) && all exprIsCheap args
isPap fun n_val_args = False
\end{code}
-exprOkForSpeculation returns True of an UNLIFTED-TYPE expression that it is safe
-to evaluate even if normal order eval might not evaluate the expression
-at all. E.G.
+exprOkForSpeculation returns True of an expression that it is
+
+ * safe to evaluate even if normal order eval might not
+ evaluate the expression at all, or
+
+ * safe *not* to evaluate even if normal order would do so
+
+It returns True iff
+
+ the expression guarantees to terminate,
+ soon,
+ without raising an exceptoin
+
+E.G.
let x = case y# +# 1# of { r# -> I# r# }
in E
==>
\begin{code}
exprOkForSpeculation :: CoreExpr -> Bool
-exprOkForSpeculation (Var v) = True -- Unlifted type => already evaluated
-
+exprOkForSpeculation (Var v) = isUnLiftedType (idType v)
exprOkForSpeculation (Note _ e) = exprOkForSpeculation e
-exprOkForSpeculation (Let (NonRec b r) e) = isUnLiftedType (idType b) &&
- exprOkForSpeculation r &&
- exprOkForSpeculation e
-exprOkForSpeculation (Let (Rec _) _) = False
-exprOkForSpeculation (Case _ _ _) = False -- Conservative
-exprOkForSpeculation (App _ _) = False
exprOkForSpeculation (Con con args)
= conOkForSpeculation con &&
and (zipWith ok (filter isValArg args) (fst (conStrictness con)))
where
ok arg demand | isLazy demand = True
- | isPrim demand = exprOkForSpeculation arg
- | otherwise = False
+ | otherwise = exprOkForSpeculation arg
-exprOkForSpeculation other = panic "exprOkForSpeculation"
- -- Lam, Type
+exprOkForSpeculation other = False -- Conservative
\end{code}
\begin{code}
exprArity :: CoreExpr -> Int -- How many value lambdas are at the top
-exprArity (Lam b e) | isTyVar b = exprArity e
- | otherwise = 1 + exprArity e
-exprArity other = 0
+exprArity (Lam b e) | isTyVar b = exprArity e
+ | otherwise = 1 + exprArity e
+exprArity (Note note e) | ok_note note = exprArity e
+exprArity other = 0
+\end{code}
+
+
+\begin{code}
+exprGenerousArity :: CoreExpr -> Int -- The number of args the thing can be applied to
+ -- without doing much work
+-- This is used when eta expanding
+-- e ==> \xy -> e x y
+--
+-- It returns 1 (or more) to:
+-- case x of p -> \s -> ...
+-- because for I/O ish things we really want to get that \s to the top.
+-- We are prepared to evaluate x each time round the loop in order to get that
+-- Hence "generous" arity
+
+exprGenerousArity (Var v) = arityLowerBound (getIdArity v)
+exprGenerousArity (Note note e)
+ | ok_note note = exprGenerousArity e
+exprGenerousArity (Lam x e)
+ | isId x = 1 + exprGenerousArity e
+ | otherwise = exprGenerousArity e
+exprGenerousArity (Let bind body)
+ | all exprIsCheap (rhssOfBind bind) = exprGenerousArity body
+exprGenerousArity (Case scrut _ alts)
+ | exprIsCheap scrut = min_zero [exprGenerousArity rhs | (_,_,rhs) <- alts]
+exprGenerousArity other = 0 -- Could do better for applications
+
+min_zero :: [Int] -> Int -- Find the minimum, but zero is the smallest
+min_zero (x:xs) = go x xs
+ where
+ go 0 xs = 0 -- Nothing beats zero
+ go min [] = min
+ go min (x:xs) | x < min = go x xs
+ | otherwise = go min xs
+
+ok_note (SCC _) = False -- (Over?) conservative
+ok_note (TermUsg _) = False -- Doesn't matter much
+
+ok_note (Coerce _ _) = True
+ -- We *do* look through coerces when getting arities.
+ -- Reason: arities are to do with *representation* and
+ -- work duplication.
+
+ok_note InlineCall = True
+ok_note InlineMe = False
+ -- This one is a bit more surprising, but consider
+ -- f = _inline_me (\x -> e)
+ -- We DO NOT want to eta expand this to
+ -- f = \x -> (_inline_me (\x -> e)) x
+ -- because the _inline_me gets dropped now it is applied,
+ -- giving just
+ -- f = \x -> e
+ -- A Bad Idea
\end{code}
arityInfo, ppArityInfo, ppFlavourInfo, flavourInfo,
demandInfo, updateInfo, ppUpdateInfo, specInfo,
strictnessInfo, ppStrictnessInfo, cafInfo, ppCafInfo,
- cprInfo, ppCprInfo, lbvarInfo
+ cprInfo, ppCprInfo, lbvarInfo,
+ workerInfo, ppWorkerInfo
)
import Const ( Con(..), DataCon )
import DataCon ( isTupleCon, isUnboxedTupleCon )
ppFlavourInfo (flavourInfo info),
ppArityInfo a,
ppUpdateInfo u,
+ ppWorkerInfo (workerInfo info),
ppStrictnessInfo s,
ppr d,
ppCafInfo c,
substTy, substTheta,
-- Expression stuff
- substExpr, substRules
+ substExpr, substIdInfo
) where
#include "HsVersions.h"
-
import CoreSyn ( Expr(..), Bind(..), Note(..), CoreExpr, CoreBndr,
CoreRules(..), CoreRule(..), emptyCoreRules, isEmptyCoreRules
)
import VarEnv
import Var ( setVarUnique, isId )
import Id ( idType, setIdType )
-import IdInfo ( zapFragileIdInfo )
+import IdInfo ( IdInfo, zapFragileIdInfo,
+ specInfo, setSpecInfo,
+ workerExists, workerInfo, setWorkerInfo, WorkerInfo
+ )
import UniqSupply ( UniqSupply, uniqFromSupply, splitUniqSupply )
import Var ( Var, IdOrTyVar, Id, TyVar, isTyVar, maybeModifyIdInfo )
import Outputable
%************************************************************************
%* *
-\section{Rule substitution}
+\section{IdInfo substitution}
%* *
%************************************************************************
\begin{code}
+substIdInfo :: Subst -> IdInfo -> IdInfo
+substIdInfo subst info
+ = info2
+ where
+ info1 | isEmptyCoreRules old_rules = info
+ | otherwise = info `setSpecInfo` substRules subst old_rules
+
+ info2 | not (workerExists old_wrkr) = info1
+ | otherwise = info1 `setWorkerInfo` substWorker subst old_wrkr
+
+ old_rules = specInfo info
+ old_wrkr = workerInfo info
+
+substWorker :: Subst -> WorkerInfo -> WorkerInfo
+substWorker subst Nothing
+ = Nothing
+substWorker subst (Just w)
+ = case lookupSubst subst w of
+ Nothing -> Just w
+ Just (DoneEx (Var w1)) -> Just w1
+ Just (DoneEx other) -> WARN( True, text "substWorker: DoneEx" <+> ppr w )
+ Nothing -- Worker has got substituted away altogether
+ Just (ContEx se1 e) -> WARN( True, text "substWorker: ContEx" <+> ppr w )
+ Nothing -- Ditto
+
substRules :: Subst -> CoreRules -> CoreRules
substRules subst (Rules rules rhs_fvs)
= Rules (map do_subst rules)
import RnEnv ( availName )
import TcInstUtil ( InstInfo(..) )
-import WorkWrap ( getWorkerId )
import CmdLineOpts
import Id ( Id, idType, idInfo, omitIfaceSigForId, isUserExportedId,
import DataCon ( StrictnessMark(..), dataConSig, dataConFieldLabels, dataConStrictMarks )
import IdInfo ( IdInfo, StrictnessInfo, ArityInfo, InlinePragInfo(..), inlinePragInfo,
arityInfo, ppArityInfo,
- strictnessInfo, ppStrictnessInfo,
+ strictnessInfo, ppStrictnessInfo, isBottomingStrictness,
cafInfo, ppCafInfo, specInfo,
cprInfo, ppCprInfo,
- workerExists, workerInfo, isBottomingStrictness
+ workerExists, workerInfo, ppWorkerInfo
)
import CoreSyn ( CoreExpr, CoreBind, Bind(..), rulesRules, rulesRhsFreeVars )
import CoreFVs ( exprSomeFreeVars, ruleSomeLhsFreeVars, ruleSomeFreeVars )
arity_pretty,
caf_pretty,
cpr_pretty,
- strict_pretty,
+ strict_pretty,
+ wrkr_pretty,
unfold_pretty,
ptext SLIT("##-}")]
------------ CPR Info --------------
cpr_pretty = ppCprInfo (cprInfo idinfo)
- ------------ Strictness and Worker --------------
+ ------------ Strictness --------------
strict_info = strictnessInfo idinfo
- work_info = workerInfo idinfo
- has_worker = workerExists work_info
bottoming_fn = isBottomingStrictness strict_info
- strict_pretty = ppStrictnessInfo strict_info <+> wrkr_pretty
+ strict_pretty = ppStrictnessInfo strict_info
- wrkr_pretty | not has_worker = empty
- | otherwise = ppr work_id
+ ------------ Worker --------------
+ work_info = workerInfo idinfo
+ has_worker = workerExists work_info
+ wrkr_pretty = ppWorkerInfo work_info
+ Just work_id = work_info
--- (Just work_id) = work_info
--- Temporary fix. We can't use the worker id saved by the w/w
--- pass because later optimisations may have changed it. So try
--- to snaffle from the wrapper code again ...
- work_id = getWorkerId id rhs
------------ Unfolding --------------
inline_pragma = inlinePragInfo idinfo
id_info :: { [HsIdInfo RdrName] }
: { [] }
| id_info_item id_info { $1 : $2 }
- | strict_info id_info { $1 ++ $2 }
id_info_item :: { HsIdInfo RdrName }
- : '__A' arity_info { HsArity $2 }
+ : '__A' INTEGER { HsArity (exactArity (fromInteger $2)) }
| '__U' core_expr { HsUnfold $1 (Just $2) }
| '__U' { HsUnfold $1 Nothing }
+ | '__M' { HsCprInfo $1 }
+ | '__S' { HsStrictness (HsStrictnessInfo $1) }
| '__C' { HsNoCafRefs }
-
-strict_info :: { [HsIdInfo RdrName] }
- : cpr worker { ($1:$2) }
- | strict worker { ($1:$2) }
- | cpr strict worker { ($1:$2:$3) }
-
-cpr :: { HsIdInfo RdrName }
- : '__M' { HsCprInfo $1 }
-
-strict :: { HsIdInfo RdrName }
- : '__S' { HsStrictness (HsStrictnessInfo $1) }
-
-worker :: { [HsIdInfo RdrName] }
- : qvar_name { [HsWorker $1] }
- | {- nothing -} { [] }
-
-arity_info :: { ArityInfo }
- : INTEGER { exactArity (fromInteger $1) }
+ | '__P' qvar_name { HsWorker $2 }
-------------------------------------------------------
core_expr :: { UfExpr RdrName }
-- The current slurped-set records all local things
getSlurped `thenRn` \ source_binders ->
- slurpSourceRefs source_binders source_fvs `thenRn` \ (decls1, needed1, inst_gates) ->
-
- -- Now we can get the instance decls
- slurpInstDecls decls1 needed1 inst_gates `thenRn` \ (decls2, needed2) ->
+ slurpSourceRefs source_binders source_fvs `thenRn` \ (decls, needed) ->
-- And finally get everything else
- closeDecls decls2 needed2
+ closeDecls decls needed
-------------------------------------------------------
slurpSourceRefs :: NameSet -- Variables defined in source
-> FreeVars -- Variables referenced in source
-> RnMG ([RenamedHsDecl],
- FreeVars, -- Un-satisfied needs
- FreeVars) -- "Gates"
+ FreeVars) -- Un-satisfied needs
-- The declaration (and hence home module) of each gate has
-- already been loaded
slurpSourceRefs source_binders source_fvs
- = go [] -- Accumulating decls
- emptyFVs -- Unsatisfied needs
- source_fvs -- Accumulating gates
- (nameSetToList source_fvs) -- Gates whose defn hasn't been loaded yet
+ = go_outer [] -- Accumulating decls
+ emptyFVs -- Unsatisfied needs
+ emptyFVs -- Accumulating gates
+ (nameSetToList source_fvs) -- Things whose defn hasn't been loaded yet
where
- go decls fvs gates []
+ -- The outer loop repeatedly slurps the decls for the current gates
+ -- and the instance decls
+
+ -- The outer loop is needed because consider
+ -- instance Foo a => Baz (Maybe a) where ...
+ -- It may be that @Baz@ and @Maybe@ are used in the source module,
+ -- but not @Foo@; so we need to chase @Foo@ too.
+ --
+ -- We also need to follow superclass refs. In particular, 'chasing @Foo@' must
+ -- include actually getting in Foo's class decl
+ -- class Wib a => Foo a where ..
+ -- so that its superclasses are discovered. The point is that Wib is a gate too.
+ -- We do this for tycons too, so that we look through type synonyms.
+
+ go_outer decls fvs all_gates []
+ = returnRn (decls, fvs)
+
+ go_outer decls fvs all_gates refs -- refs are not necessarily slurped yet
+ = traceRn (text "go_outer" <+> ppr refs) `thenRn_`
+ go_inner decls fvs emptyFVs refs `thenRn` \ (decls1, fvs1, gates1) ->
+ getImportedInstDecls (all_gates `plusFV` gates1) `thenRn` \ inst_decls ->
+ rnInstDecls decls1 fvs1 gates1 inst_decls `thenRn` \ (decls2, fvs2, gates2) ->
+ go_outer decls2 fvs2 (all_gates `plusFV` gates2)
+ (nameSetToList (gates2 `minusNameSet` all_gates))
+ -- Knock out the all_gates because even ifwe don't slurp any new
+ -- decls we can get some apparently-new gates from wired-in names
+
+ go_inner decls fvs gates []
= returnRn (decls, fvs, gates)
- go decls fvs gates (wanted_name:refs)
+ go_inner decls fvs gates (wanted_name:refs)
| isWiredInName wanted_name
= load_home wanted_name `thenRn_`
- go decls fvs (gates `plusFV` getWiredInGates wanted_name) refs
+ go_inner decls fvs (gates `plusFV` getWiredInGates wanted_name) refs
| otherwise
= importDecl wanted_name `thenRn` \ maybe_decl ->
case maybe_decl of
- -- No declaration... (already slurped, or local)
- Nothing -> go decls fvs gates refs
+ Nothing -> go_inner decls fvs gates refs -- No declaration... (already slurped, or local)
Just decl -> rnIfaceDecl decl `thenRn` \ (new_decl, fvs1) ->
- go (new_decl : decls)
- (fvs1 `plusFV` fvs)
- (gates `plusFV` getGates source_fvs new_decl)
- refs
+ go_inner (new_decl : decls)
+ (fvs1 `plusFV` fvs)
+ (gates `plusFV` getGates source_fvs new_decl)
+ refs
-- When we find a wired-in name we must load its
-- home module so that we find any instance decls therein
returnRn ()
where
doc = ptext SLIT("need home module for wired in thing") <+> ppr name
-\end{code}
-%
-@slurpInstDecls@ imports appropriate instance decls.
-It has to incorporate a loop, because consider
-\begin{verbatim}
- instance Foo a => Baz (Maybe a) where ...
-\end{verbatim}
-It may be that @Baz@ and @Maybe@ are used in the source module,
-but not @Foo@; so we need to chase @Foo@ too.
-\begin{code}
-slurpInstDecls decls needed gates
- = go decls needed gates gates
- where
- go decls needed all_gates new_gates
- | isEmptyFVs new_gates
- = returnRn (decls, needed)
-
- | otherwise
- = getImportedInstDecls all_gates `thenRn` \ inst_decls ->
- rnInstDecls decls needed emptyFVs inst_decls `thenRn` \ (decls1, needed1, new_gates) ->
- go decls1 needed1 (all_gates `plusFV` new_gates) new_gates
+rnInstDecls decls fvs gates []
+ = returnRn (decls, fvs, gates)
+rnInstDecls decls fvs gates (d:ds)
+ = rnIfaceDecl d `thenRn` \ (new_decl, fvs1) ->
+ rnInstDecls (new_decl:decls)
+ (fvs1 `plusFV` fvs)
+ (gates `plusFV` getInstDeclGates new_decl)
+ ds
+\end{code}
- rnInstDecls decls fvs gates []
- = returnRn (decls, fvs, gates)
- rnInstDecls decls fvs gates (d:ds)
- = rnIfaceDecl d `thenRn` \ (new_decl, fvs1) ->
- rnInstDecls (new_decl:decls)
- (fvs1 `plusFV` fvs)
- (gates `plusFV` getInstDeclGates new_decl)
- ds
-
+\begin{code}
-------------------------------------------------------
-- closeDecls keeps going until the free-var set is empty
closeDecls decls needed
\begin{code}
getImportedInstDecls :: NameSet -> RnMG [(Module,RdrNameHsDecl)]
getImportedInstDecls gates
- = -- First, ensure that the home module of each gate is loaded
- mapRn_ load_home gate_list `thenRn_`
-
- -- Next, load any orphan-instance modules that aren't aready loaded
+ = -- First, load any orphan-instance modules that aren't aready loaded
-- Orphan-instance modules are recorded in the module dependecnies
getIfacesRn `thenRn` \ ifaces ->
let
traceRn (sep [text "getImportedInstDecls:",
nest 4 (fsep (map ppr gate_list)),
- text "Slurped" <+> int (length decls)
- <+> text "instance declarations"]) `thenRn_`
+ text "Slurped" <+> int (length decls) <+> text "instance declarations",
+ nest 4 (vcat (map ppr_brief_inst_decl decls))]) `thenRn_`
returnRn decls
where
gate_list = nameSetToList gates
= loadHomeInterface (ppr gate <+> text "is an instance gate") gate `thenRn_`
returnRn ()
+ppr_brief_inst_decl (mod, InstD (InstDecl inst_ty _ _ _ _))
+ = case inst_ty of
+ HsForAllTy _ _ tau -> ppr tau
+ other -> ppr inst_ty
+
getImportedRules :: RnMG [(Module,RdrNameHsDecl)]
getImportedRules
= getIfacesRn `thenRn` \ ifaces ->
-> (FloatStats, FloatBinds, CoreBind, IdEnv Level)
floatBind env lvl (NonRec (name,level) rhs)
- = case (floatExpr env level rhs) of { (fs, rhs_floats, rhs') ->
-
- -- A good dumping point
- case (partitionByMajorLevel level rhs_floats) of { (rhs_floats', heres) ->
-
- (fs, rhs_floats',
- NonRec name (install heres rhs'),
+ = case (floatRhs env level rhs) of { (fs, rhs_floats, rhs') ->
+ (fs, rhs_floats,
+ NonRec name rhs',
extendVarEnv env name level)
- }}
+ }
floatBind env lvl bind@(Rec pairs)
= case (unzip3 (map do_pair pairs)) of { (fss, rhss_floats, new_pairs) ->
bind_level = getBindLevel bind
do_pair ((name, level), rhs)
- = case (floatExpr new_env level rhs) of { (fs, rhs_floats, rhs') ->
-
- -- A good dumping point
- case (partitionByMajorLevel level rhs_floats) of { (rhs_floats', heres) ->
-
- (fs, rhs_floats', (name, install heres rhs'))
- }}
+ = case (floatRhs new_env level rhs) of { (fs, rhs_floats, rhs') ->
+ (fs, rhs_floats, (name, rhs'))
+ }
\end{code}
%************************************************************************
%************************************************************************
\begin{code}
-floatExpr :: IdEnv Level
- -> Level
- -> LevelledExpr
- -> (FloatStats, FloatBinds, CoreExpr)
+floatExpr, floatRhs
+ :: IdEnv Level
+ -> Level
+ -> LevelledExpr
+ -> (FloatStats, FloatBinds, CoreExpr)
+
+floatRhs env lvl arg
+ = case (floatExpr env lvl arg) of { (fsa, floats, arg') ->
+ case (partitionByMajorLevel lvl floats) of { (floats', heres) ->
+ -- Dump bindings that aren't going to escape from a lambda
+ -- This is to avoid floating the x binding out of
+ -- f (let x = e in b)
+ -- unnecessarily. It even causes a bug to do so if we have
+ -- y = writeArr# a n (let x = e in b)
+ -- because the y binding is an expr-ok-for-speculation one.
+ (fsa, floats', install heres arg') }}
floatExpr env _ (Var v) = (zeroStats, [], Var v)
floatExpr env _ (Type ty) = (zeroStats, [], Type ty)
floatExpr env lvl (Con con as)
- = case floatList (floatExpr env lvl) as of { (stats, floats, as') ->
+ = case floatList (floatRhs env lvl) as of { (stats, floats, as') ->
(stats, floats, Con con as') }
floatExpr env lvl (App e a)
= case (floatExpr env lvl e) of { (fse, floats_e, e') ->
- case (floatExpr env lvl a) of { (fsa, floats_a, a') ->
+ case (floatRhs env lvl a) of { (fsa, floats_a, a') ->
(fse `add_stats` fsa, floats_e ++ floats_a, App e' a') }}
floatExpr env lvl (Lam (tv,incd_lvl) e)
partitionByMajorLevel ctxt_lvl defns
= partition float_further defns
where
- float_further (my_lvl, _) = my_lvl `ltMajLvl` ctxt_lvl ||
- isTopLvl my_lvl
+ float_further (my_lvl, _) = my_lvl `lt_major` ctxt_lvl
+
+my_lvl `lt_major` ctxt_lvl = my_lvl `ltMajLvl` ctxt_lvl ||
+ isTopLvl my_lvl
partitionByLevel ctxt_lvl defns
= partition float_further defns
import CoreFVs ( idRuleVars )
import CoreUtils ( exprIsTrivial )
import Const ( Con(..), Literal(..) )
-import Id ( isSpecPragmaId,
+import Id ( isSpecPragmaId, isOneShotLambda,
getInlinePragma, setInlinePragma,
isExportedId, modifyIdInfo, idInfo,
getIdSpecialisation,
mkLams tagged_binders body') }
where
(binders, body) = collectBinders expr
- (linear, env_body) = getCtxt env (count isId binders)
+ (linear, env_body) = oneShotGroup env (filter isId binders)
occAnal env (Case scrut bndr alts)
= case mapAndUnzip (occAnalAlt alt_env) alts of { (alts_usage_s, alts') ->
setCtxt :: OccEnv -> CtxtTy -> OccEnv
setCtxt (OccEnv ifun cands _) ctxt = OccEnv ifun cands ctxt
-getCtxt :: OccEnv -> Int -> (Bool, OccEnv) -- True <=> this is a linear lambda
- -- The Int is the number of lambdas
-getCtxt env@(OccEnv ifun cands []) n = (False, env)
-getCtxt (OccEnv ifun cands ctxt) n = (and (take n ctxt), OccEnv ifun cands (drop n ctxt))
- -- Only return True if *all* the lambdas are linear
+oneShotGroup :: OccEnv -> [Id] -> (Bool, OccEnv) -- True <=> this is a one-shot linear lambda group
+ -- The [Id] are the binders
+oneShotGroup (OccEnv ifun cands ctxt) bndrs
+ = (go bndrs ctxt, OccEnv ifun cands (drop (length bndrs) ctxt))
+ where
+ -- Only return True if *all* the lambdas are linear
+ go (bndr:bndrs) (lin:ctxt) = (lin || isOneShotLambda bndr) && go bndrs ctxt
+ go [] ctxt = True
+ go bndrs [] = all isOneShotLambda bndrs
zapCtxt env@(OccEnv ifun cands []) = env
zapCtxt (OccEnv ifun cands _ ) = OccEnv ifun cands []
let
subst = mkSubst emptyVarSet subst_env
v' = setVarUnique v uniq
- v'' = apply_to_rules subst v'
+ v'' = modifyIdInfo (substIdInfo subst) v'
subst_env' = extendSubstEnv subst_env v (DoneEx (Var v''))
lvl_env' = extendVarEnv lvl_env v lvl
in
cloneVars :: TopLevelFlag -> LevelEnv -> [Id] -> Level -> LvlM (LevelEnv, [Id])
cloneVars TopLevel env vs lvl
= returnUs (env, vs) -- Don't clone top level things
-cloneVars NotTopLevel (lvl_env, subst_env) vs lvl
+cloneVars NotTopLevel (lvl_env, subst_env) vs lvl
= getUniquesUs (length vs) `thenLvl` \ uniqs ->
let
subst = mkSubst emptyVarSet subst_env'
vs' = zipWith setVarUnique vs uniqs
- vs'' = map (apply_to_rules subst) vs'
+ vs'' = map (modifyIdInfo (substIdInfo subst)) vs'
subst_env' = extendSubstEnvList subst_env vs [DoneEx (Var v'') | v'' <- vs'']
lvl_env' = extendVarEnvList lvl_env (vs `zip` repeat lvl)
in
returnUs ((lvl_env', subst_env'), vs'')
-
--- Apply the substitution to the rules
-apply_to_rules subst id
- = modifyIdInfo go_spec id
- where
- go_spec info = info `setSpecInfo` substRules subst (specInfo info)
\end{code}
import CmdLineOpts ( opt_SimplDoLambdaEtaExpansion, opt_SimplCaseMerge )
import CoreSyn
import CoreFVs ( exprFreeVars )
-import CoreUtils ( exprIsTrivial, cheapEqExpr, coreExprType, exprIsCheap )
+import CoreUtils ( exprIsTrivial, cheapEqExpr, coreExprType, exprIsCheap, exprGenerousArity )
import Subst ( substBndrs, substBndr, substIds )
import Id ( Id, idType, getIdArity, isId, idName,
getInlinePragma, setInlinePragma,
wanting a suitable number of extra args.
NB: the Ei may have unlifted type, but the simplifier (which is applied
-to the result) deals OK with this).
+to the result) deals OK with this.
There is no point in looking for a combination of the two,
because that would leave use with some lets sandwiched between lambdas;
(x_bndrs, body) = collectValBinders rhs
(fun, args) = collectArgs body
trivial_args = map exprIsTrivial args
- fun_arity = case fun of
- Var v -> arityLowerBound (getIdArity v)
- other -> 0
+ fun_arity = exprGenerousArity fun
bind_z_arg (arg, trivial_arg)
| trivial_arg = returnSmpl (Nothing, arg)
y_tys = take no_extras_wanted potential_extra_arg_tys
no_extras_wanted :: Int
- no_extras_wanted =
+ no_extras_wanted = 0 `max`
-- We used to expand the arity to the previous arity fo the
-- function; but this is pretty dangerous. Consdier
-- (bndr_arity - no_of_xs) `max`
-- See if the body could obviously do with more args
- (fun_arity - valArgCount args) `max`
+ (fun_arity - valArgCount args)
+-- This case is now deal with by exprGenerousArity
-- Finally, see if it's a state transformer, and xs is non-null
-- (so it's also a function not a thunk) in which
-- case we eta-expand on principle! This can waste work,
-- \ x -> let {..} in \ s -> f (...) s
-- AND f RETURNED A FUNCTION. That is, 's' wasn't the only
-- potential extra arg.
- case (x_bndrs, potential_extra_arg_tys) of
- (_:_, ty:_) -> case splitTyConApp_maybe ty of
- Just (tycon,_) | tycon == statePrimTyCon -> 1
- other -> 0
- other -> 0
+-- case (x_bndrs, potential_extra_arg_tys) of
+-- (_:_, ty:_) -> case splitTyConApp_maybe ty of
+-- Just (tycon,_) | tycon == statePrimTyCon -> 1
+-- other -> 0
+-- other -> 0
\end{code}
getIdUnfolding, setIdUnfolding, isExportedId,
getIdSpecialisation, setIdSpecialisation,
getIdDemandInfo, setIdDemandInfo,
- getIdArity, setIdArity,
+ getIdArity, setIdArity, setIdInfo,
getIdStrictness,
setInlinePragma, getInlinePragma, idMustBeINLINEd,
setOneShotLambda
)
import IdInfo ( InlinePragInfo(..), OccInfo(..), StrictnessInfo(..),
ArityInfo(..), atLeastArity, arityLowerBound, unknownArity,
- specInfo, inlinePragInfo, zapLamIdInfo
+ specInfo, inlinePragInfo, zapLamIdInfo, setArityInfo, setInlinePragInfo, setUnfoldingInfo
)
import Demand ( Demand, isStrict, wwLazy )
import Const ( isWHNFCon, conOkForAlt )
import CoreSyn
import CoreFVs ( exprFreeVars )
import CoreUnfold ( Unfolding, mkOtherCon, mkUnfolding, otherCons,
- callSiteInline, blackListed
+ callSiteInline, blackListed, hasSomeUnfolding
)
import CoreUtils ( cheapEqExpr, exprIsDupable, exprIsCheap, exprIsTrivial,
coreExprType, coreAltsType, exprArity, exprIsValue,
funResultTy, isDictTy, isDataType, applyTy, applyTys, mkFunTys
)
import Subst ( Subst, mkSubst, emptySubst, substExpr, substTy,
- substEnv, lookupInScope, lookupSubst, substRules
+ substEnv, lookupInScope, lookupSubst, substIdInfo
)
import TyCon ( isDataTyCon, tyConDataCons, tyConClass_maybe, tyConArity, isDataTyCon )
import TysPrim ( realWorldStatePrimTy )
| otherwise
= getSubst `thenSmpl` \ subst ->
let
- bndr_info = idInfo old_bndr
- old_rules = specInfo bndr_info
- new_rules = substRules subst old_rules
-
- -- The new binding site Id needs its specialisations re-attached
- bndr_w_arity = new_bndr `setIdArity` ArityAtLeast (exprArity new_rhs)
-
- binding_site_id
- | isEmptyCoreRules old_rules = bndr_w_arity
- | otherwise = bndr_w_arity `setIdSpecialisation` new_rules
-
+ -- We make new IdInfo for the new binder by starting from the old binder,
+ -- doing appropriate substitutions,
+ old_bndr_info = idInfo old_bndr
+ new_bndr_info = substIdInfo subst old_bndr_info
+ `setArityInfo` ArityAtLeast (exprArity new_rhs)
+
+ -- At the *binding* site we want to zap the now-out-of-date inline
+ -- pragma, in case the expression is simplified a second time.
+ -- This has already been done in new_bndr, so we get it from there
+ binding_site_id = new_bndr `setIdInfo`
+ (new_bndr_info `setInlinePragInfo` getInlinePragma new_bndr)
+
-- At the occurrence sites we want to know the unfolding,
- -- and the occurrence info of the original
- -- (simplBinder cleaned up the inline prag of the original
- -- to eliminate un-stable info, in case this expression is
- -- simplified a second time; hence the need to reattach it)
- occ_site_id = binding_site_id
- `setIdUnfolding` mkUnfolding new_rhs
- `setInlinePragma` inlinePragInfo bndr_info
+ -- We want the occurrence info of the *original*, which is already
+ -- in new_bndr_info
+ occ_site_id = new_bndr `setIdInfo`
+ (new_bndr_info `setUnfoldingInfo` mkUnfolding new_rhs)
in
modifyInScope occ_site_id thing_inside `thenSmpl` \ stuff ->
returnSmpl (addBind (NonRec binding_site_id new_rhs) stuff)
(args', result_cont) = contArgs in_scope cont
+ val_args = filter isValArg args'
+ arg_infos = map (interestingArg in_scope) val_args
inline_call = contIsInline result_cont
interesting_cont = contIsInteresting result_cont
discard_inline_cont | inline_call = discardInline cont
---------- Unfolding stuff
maybe_inline = callSiteInline black_listed inline_call
- var args' interesting_cont
+ var arg_infos interesting_cont
Just unf_template = maybe_inline
black_listed = black_list_fn var
Just (rule_name, rule_rhs, rule_args) = maybe_rule_match
+
+-- An argument is interesting if it has *some* structure
+-- We are here trying to avoid unfolding a function that
+-- is applied only to variables that have no unfolding
+-- (i.e. they are probably lambda bound): f x y z
+-- There is little point in inlining f here.
+interestingArg in_scope (Type _) = False
+interestingArg in_scope (App fn (Type _)) = interestingArg in_scope fn
+interestingArg in_scope (Var v) = hasSomeUnfolding (getIdUnfolding v')
+ where
+ v' = case lookupVarSet in_scope v of
+ Just v' -> v'
+ other -> v
+interestingArg in_scope other = True
+
+
-- First a special case
-- Don't actually inline the scrutinee when we see
-- case x of y { .... }
all (cheapEqExpr rhs1) other_rhss && all binders_unused alts
-- Check that the scrutinee can be let-bound instead of case-bound
- && ( (isUnLiftedType (idType bndr) && -- It's unlifted and floatable
- exprOkForSpeculation scrut) -- NB: scrut = an unboxed variable satisfies
+ && ( 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)
|| exprIsValue scrut -- It's already evaluated
|| var_demanded_later scrut -- It'll be demanded later
newId join_arg_ty' ( \ arg_id ->
getSwitchChecker `thenSmpl` \ chkr ->
cont_fn (Var arg_id) `thenSmpl` \ (binds, (_, rhs)) ->
- returnSmpl (Lam arg_id (mkLets binds rhs))
+ returnSmpl (Lam (setOneShotLambda arg_id) (mkLets binds rhs))
) `thenSmpl` \ join_rhs ->
-- Build the join Id and continuation
mkDupableAlt :: InId -> OutId -> SimplCont -> InAlt -> SimplM (OutStuff InAlt)
+mkDupableAlt case_bndr case_bndr' (Stop _) alt@(con, bndrs, rhs)
+ | exprIsDupable rhs
+ = -- It is worth checking for a small RHS because otherwise we
+ -- get extra let bindings that may cause an extra iteration of the simplifier to
+ -- inline back in place. Quite often the rhs is just a variable or constructor.
+ -- The Ord instance of Maybe in PrelMaybe.lhs, for example, took several extra
+ -- iterations because the version with the let bindings looked big, and so wasn't
+ -- inlined, but after the join points had been inlined it looked smaller, and so
+ -- was inlined.
+ --
+ -- But since the continuation is absorbed into the rhs, we only do this
+ -- for a Stop continuation.
+ returnSmpl ([], alt)
+
mkDupableAlt case_bndr case_bndr' cont alt@(con, bndrs, rhs)
+ | otherwise
= -- Not worth checking whether the rhs is small; the
-- inliner will inline it if so.
simplBinders bndrs $ \ bndrs' ->
-- One tiresome way to terminate: check for excess unmatched
-- template arguments
- go tpl_args [] subst
+ go tpl_args [] subst = Nothing -- Failure
+
+
+{- The code below tries to match even if there are more
+ template args than real args.
+
+ I now think this is probably a bad idea.
+ Should the template (map f xs) match (map g)? I think not.
+ For a start, in general eta expansion wastes work.
+ SLPJ July 99
+
= case eta_complete tpl_args (mkVarSet leftovers) of
Just leftovers' -> Just (rn, mkLams done (mkLams leftovers' rhs),
mk_result_args subst done)
Nothing -> Nothing
eta_complete other vars = Nothing
+-}
-----------------------
mk_result_args subst vs = map go vs
Just (DoneTy ty) -> Type ty
-- Substitution should bind them all!
+
zapOccInfo bndr | isTyVar bndr = bndr
| otherwise = maybeModifyIdInfo zapLamIdInfo bndr
\end{code}
\section[WorkWrap]{Worker/wrapper-generating back-end of strictness analyser}
\begin{code}
-module WorkWrap ( wwTopBinds, getWorkerId ) where
+module WorkWrap ( wwTopBinds ) where
#include "HsVersions.h"
setIdStrictness,
setIdWorkerInfo, getIdCprInfo )
import VarSet
-import Type ( splitAlgTyConApp_maybe )
+import Type ( isNewType )
import IdInfo ( mkStrictnessInfo, noStrictnessInfo, StrictnessInfo(..),
CprInfo(..), exactArity
)
-- if two, then a worker and a
-- wrapper.
tryWW non_rec fn_id rhs
- | (non_rec && -- Don't split if its non-recursive and small
- certainlySmallEnoughToInline unfold_guidance
+ | (non_rec && -- Don't split if its non-recursive and small
+ certainlySmallEnoughToInline (calcUnfoldingGuidance opt_UF_CreationThreshold rhs) &&
+ -- No point in worker/wrappering something that is going to be
+ -- INLINEd wholesale anyway. If the strictness analyser is run
+ -- twice, this test also prevents wrappers (which are INLINEd)
+ -- from being re-done.
+
+ not (null wrap_args && do_coerce_ww)
+ -- However, if we have f = coerce T E
+ -- then we want to w/w anyway, to get
+ -- fw = E
+ -- f = coerce T fw
+ -- We want to do this even if the binding is small and non-rec.
+ -- Reason: I've seen this situation:
+ -- let f = coerce T (\s -> E)
+ -- in \x -> case x of
+ -- p -> coerce T' f
+ -- q -> \s -> E2
+ -- If only we w/w'd f, we'd inline the coerce (because it's trivial)
+ -- to get
+ -- let fw = \s -> E
+ -- in \x -> case x of
+ -- p -> fw
+ -- q -> \s -> E2
+ -- Now we'll see that fw has arity 1, and will arity expand
+ -- the \x to get what we want.
)
- -- No point in worker/wrappering something that is going to be
- -- INLINEd wholesale anyway. If the strictness analyser is run
- -- twice, this test also prevents wrappers (which are INLINEd)
- -- from being re-done.
- || not (do_strict_ww || do_cpr_ww)
+ || not (do_strict_ww || do_cpr_ww || do_coerce_ww)
= returnUs [ (fn_id, rhs) ]
| otherwise -- Do w/w split
= mkWwBodies tyvars wrap_args
- (coreExprType body)
+ body_ty
wrap_demands
cpr_info
`thenUs` \ (wrap_fn, work_fn, work_demands) ->
where
(tyvars, wrap_args, body) = collectTyAndValBinders rhs
n_wrap_args = length wrap_args
-
+ body_ty = coreExprType body
strictness_info = getIdStrictness fn_id
has_strictness_info = case strictness_info of
StrictnessInfo _ _ -> True
do_strict_ww = has_strictness_info && worthSplitting wrap_demands result_bot
+ -------------------------------------------------------------
cpr_info = getIdCprInfo fn_id
has_cpr_info = case cpr_info of
CPRInfo _ -> True
other -> False
do_cpr_ww = has_cpr_info
- unfold_guidance = calcUnfoldingGuidance opt_UF_CreationThreshold rhs
+
+ -------------------------------------------------------------
+ -- Do the coercion thing if the body is of a newtype
+ do_coerce_ww = isNewType body_ty
+
+
+{- July 99: removed again by Simon
-- This rather (nay! extremely!) crude function looks at a wrapper function, and
-- snaffles out the worker Id from the wrapper.
work_id_try2 (App fn _) = work_id_try2 fn
work_id_try2 (Var work_id) = [work_id]
work_id_try2 other = []
+-}
\end{code}
import TysWiredIn ( unboxedTupleCon, unboxedTupleTyCon )
import Type ( isUnLiftedType, mkTyVarTys, mkTyVarTy, mkFunTys,
splitForAllTys, splitFunTys, splitFunTysN,
- splitAlgTyConApp_maybe, mkTyConApp,
+ splitAlgTyConApp_maybe, splitAlgTyConApp,
+ mkTyConApp, newTypeRep, isNewType,
Type
)
import TyCon ( isNewTyCon,
CoreExpr -> CoreExpr, -- Worker body, lacking the original function body
[Demand]) -- Strictness info for worker
-mkWwBodies tyvars args body_ty demands cpr_info
- | allAbsent demands &&
- isUnLiftedType body_ty
- = -- Horrid special case. If the worker would have no arguments, and the
- -- function returns a primitive type value, that would make the worker into
- -- an unboxed value. We box it by passing a dummy void argument, thus:
- --
- -- f = /\abc. \xyz. fw abc void
- -- fw = /\abc. \v. body
- --
- -- We use the state-token type which generates no code
- getUniqueUs `thenUs` \ void_arg_uniq ->
- let
- void_arg = mk_ww_local void_arg_uniq realWorldStatePrimTy
- in
- returnUs (\ work_id -> Note InlineMe $ -- Inline the wrapper
- mkLams tyvars $ mkLams args $
- mkApps (Var work_id)
- (map (Type . mkTyVarTy) tyvars ++ [Var realWorldPrimId]),
- \ body -> mkLams (tyvars ++ [void_arg]) body,
- [WwLazy True])
-
mkWwBodies tyvars wrap_args body_ty demands cpr_info
- | otherwise
= let
-- demands may be longer than number of args. If we aren't doing w/w
-- for strictness then demands is an infinite list of 'lazy' args.
wrap_args_w_demands = zipWith setIdDemandInfo wrap_args demands
+ (wrap_fn_coerce, work_fn_coerce) = mkWWcoerce body_ty
in
- mkWW wrap_args_w_demands `thenUs` \ (wrap_fn, work_args_w_demands, work_fn) ->
+ mkWWstr body_ty wrap_args_w_demands `thenUs` \ (work_args_w_demands, wrap_fn_str, work_fn_str) ->
- mkWWcpr body_ty cpr_info `thenUs` \ (wrap_fn_w_cpr, work_fn_w_cpr) ->
+ mkWWcpr body_ty cpr_info `thenUs` \ (wrap_fn_cpr, work_fn_cpr) ->
returnUs (\ work_id -> Note InlineMe $
mkLams tyvars $ mkLams wrap_args_w_demands $
- (wrap_fn_w_cpr . wrap_fn) (mkTyApps (Var work_id) (mkTyVarTys tyvars)),
+ (wrap_fn_coerce . wrap_fn_str . wrap_fn_cpr) $
+ mkVarApps (Var work_id) (tyvars ++ work_args_w_demands),
- \ body -> mkLams tyvars $ mkLams work_args_w_demands $
- (work_fn_w_cpr . work_fn) body,
+ \ work_body -> mkLams tyvars $ mkLams work_args_w_demands $
+ (work_fn_coerce . work_fn_str . work_fn_cpr)
+ work_body,
map getIdDemandInfo work_args_w_demands)
+\end{code}
+
+
+%************************************************************************
+%* *
+\subsection{Coercion stuff}
+%* *
+%************************************************************************
+
+The "coerce" transformation is
+ f :: T1 -> T2 -> R
+ f = \xy -> e
+===>
+ f = \xy -> coerce R R' (fw x y)
+ fw = \xy -> coerce R' R e
+
+where R' is the representation type for R.
+
+\begin{code}
+mkWWcoerce body_ty
+ | not (isNewType body_ty)
+ = (id, id)
+
+ | otherwise
+ = (wrap_fn . mkNote (Coerce body_ty rep_ty),
+ mkNote (Coerce rep_ty body_ty) . work_fn)
+ where
+ (tycon, args, _) = splitAlgTyConApp body_ty
+ rep_ty = newTypeRep tycon args
+ (wrap_fn, work_fn) = mkWWcoerce rep_ty
\end{code}
+
+%************************************************************************
+%* *
+\subsection{Strictness stuff}
+%* *
+%************************************************************************
+
+
\begin{code}
-mkWW :: [Id] -- Wrapper args; have their demand info on them
- -> UniqSM (CoreExpr -> CoreExpr, -- Wrapper body, lacking the inner call to the worker
- -- and without its lambdas
- [Id], -- Worker args; have their demand info on them
- CoreExpr -> CoreExpr) -- Worker body, lacking the original body of the function
+mkWWstr :: Type -- Body type
+ -> [Id] -- Wrapper args; have their demand info on them
+ -> UniqSM ([Id], -- Worker args; have their demand info on them
+
+ CoreExpr -> CoreExpr, -- Wrapper body, lacking the inner call to the worker
+ -- and without its lambdas
+ -- At the call site, the worker args are bound
+
+ CoreExpr -> CoreExpr) -- Worker body, lacking the original body of the function,
+ -- and without its lambdas
+
+mkWWstr body_ty wrap_args
+ = mk_ww wrap_args `thenUs` \ (work_args, wrap_fn, work_fn) ->
+
+ if null work_args && isUnLiftedType body_ty then
+ -- Horrid special case. If the worker would have no arguments, and the
+ -- function returns a primitive type value, that would make the worker into
+ -- an unboxed value. We box it by passing a dummy void argument, thus:
+ --
+ -- f = /\abc. \xyz. fw abc void
+ -- fw = /\abc. \v. body
+ --
+ -- We use the state-token type which generates no code
+ getUniqueUs `thenUs` \ void_arg_uniq ->
+ let
+ void_arg = mk_ww_local void_arg_uniq realWorldStatePrimTy
+ in
+ returnUs ([void_arg],
+ wrap_fn . Let (NonRec void_arg (Var realWorldPrimId)),
+ work_fn)
+ else
+ returnUs (work_args, wrap_fn, work_fn)
+
-- Empty case
-mkWW []
- = returnUs (\ wrapper_body -> wrapper_body,
- [],
+mk_ww []
+ = returnUs ([],
+ \ wrapper_body -> wrapper_body,
\ worker_body -> worker_body)
-mkWW (arg : ds)
+mk_ww (arg : ds)
= case getIdDemandInfo arg of
-- Absent case
WwLazy True ->
- mkWW ds `thenUs` \ (wrap_fn, worker_args, work_fn) ->
- returnUs (\ wrapper_body -> wrap_fn wrapper_body,
- worker_args,
- \ worker_body -> mk_absent_let arg (work_fn worker_body))
-
+ mk_ww ds `thenUs` \ (worker_args, wrap_fn, work_fn) ->
+ returnUs (worker_args, wrap_fn, mk_absent_let arg . work_fn)
-- Unpack case
WwUnpack new_or_data True cs ->
getUniquesUs (length inst_con_arg_tys) `thenUs` \ uniqs ->
let
unpk_args = zipWith mk_ww_local uniqs inst_con_arg_tys
- unpk_args_w_ds = zipWithEqual "mkWW" setIdDemandInfo unpk_args cs
+ unpk_args_w_ds = zipWithEqual "mk_ww" setIdDemandInfo unpk_args cs
in
- mkWW (unpk_args_w_ds ++ ds) `thenUs` \ (wrap_fn, worker_args, work_fn) ->
- returnUs (\ wrapper_body -> mk_unpk_case new_or_data arg unpk_args data_con arg_tycon
- (wrap_fn wrapper_body),
- worker_args,
- \ worker_body -> work_fn (mk_pk_let new_or_data arg data_con
- tycon_arg_tys unpk_args worker_body))
+ mk_ww (unpk_args_w_ds ++ ds) `thenUs` \ (worker_args, wrap_fn, work_fn) ->
+ returnUs (worker_args,
+ mk_unpk_case new_or_data arg unpk_args data_con arg_tycon . wrap_fn,
+ work_fn . mk_pk_let new_or_data arg data_con tycon_arg_tys unpk_args)
where
inst_con_arg_tys = dataConArgTys data_con tycon_arg_tys
(arg_tycon, tycon_arg_tys, data_con)
Nothing ->
panic "mk_ww_arg_processing: not datatype"
-
-- Other cases
other_demand ->
- mkWW ds `thenUs` \ (wrap_fn, worker_args, work_fn) ->
- returnUs (\ wrapper_body -> wrap_fn (App wrapper_body (Var arg)),
- arg : worker_args,
- work_fn)
+ mk_ww ds `thenUs` \ (worker_args, wrap_fn, work_fn) ->
+ returnUs (arg : worker_args, wrap_fn, work_fn)
\end{code}
+
+%************************************************************************
+%* *
+\subsection{CPR stuff}
+%* *
+%************************************************************************
+
+
@mkWWcpr@ takes the worker/wrapper pair produced from the strictness
info and adds in the CPR transformation. The worker returns an
unboxed tuple containing non-CPR components. The wrapper takes this
map fst contents),
mkTyConApp (unboxedTupleTyCon (length contents))
(map snd contents))
-
-
\end{code}
import Util ( mapAccumL, zipEqual, zipWithEqual,
zipWith3Equal, nOfThem, assocDefault )
import Panic ( panic, assertPanic )
-import Maybes ( maybeToBool, assocMaybe )
+import Maybes ( maybeToBool )
import Constants
import List ( partition, intersperse )
import Char ( isAlpha )
lookupFixity :: Fixities -> Name -> Fixity
lookupFixity fixs_assoc nm = assocDefault defaultFixity fixs_assoc nm
+isInfixOccName :: String -> Bool
+isInfixOccName str =
+ case str of
+ (':':_) -> True
+ _ -> False
+
\end{code}
\begin{code}
tcWorkerInfo unf_env ty info worker_name
- | arity == 0
+ | not (hasArity arity_info)
= pprPanic "Worker with no arity info" (ppr worker_name)
| otherwise
where
-- We are relying here on arity, cpr and strictness info always appearing
-- before worker info, fingers crossed ....
- arity = arityLowerBound (arityInfo info)
- cpr_info = cprInfo info
- demands = case strictnessInfo info of
+ arity_info = arityInfo info
+ arity = arityLowerBound arity_info
+ cpr_info = cprInfo info
+ demands = case strictnessInfo info of
StrictnessInfo d _ -> d
_ -> repeat wwLazy -- Noncommittal
\end{code}
mkAppTy, mkAppTys, splitAppTy, splitAppTys, splitAppTy_maybe,
- mkFunTy, mkFunTys, splitFunTy_maybe, splitFunTys, splitFunTysN, funResultTy,
+ mkFunTy, mkFunTys, splitFunTy_maybe, splitFunTys, splitFunTysN,
+ funResultTy, funArgTy,
zipFunTys,
mkTyConApp, mkTyConTy, splitTyConApp_maybe,
splitAlgTyConApp_maybe, splitAlgTyConApp,
mkDictTy, splitDictTy_maybe, isDictTy,
- mkSynTy, isSynTy, deNoteType, repType,
+ mkSynTy, isSynTy, deNoteType, repType, newTypeRep,
mkUsgTy, isUsgTy{- dont use -}, isNotUsgTy, splitUsgTy, unUsgTy, tyUsg,
mkSigmaTy, splitSigmaTy,
-- Lifting and boxity
- isUnLiftedType, isUnboxedType, isUnboxedTupleType, isAlgType, isDataType,
+ isUnLiftedType, isUnboxedType, isUnboxedTupleType, isAlgType, isDataType, isNewType,
typePrimRep,
-- Free variables
funResultTy (FunTy arg res) = res
funResultTy (NoteTy _ ty) = funResultTy ty
funResultTy ty = pprPanic "funResultTy" (pprType ty)
+
+funArgTy :: Type -> Type
+funArgTy (FunTy arg res) = arg
+funArgTy (NoteTy _ ty) = funArgTy ty
+funArgTy ty = pprPanic "funArgTy" (pprType ty)
\end{code}
\begin{code}
repType :: Type -> Type
-repType (NoteTy _ ty) = repType ty
-repType (ForAllTy _ ty) = repType ty
-repType (TyConApp tc tys) | isNewTyCon tc
- = case splitFunTy_maybe (applyTys (dataConType (head (tyConDataCons tc))) tys) of
- Just (rep_ty, _) -> repType rep_ty
-repType other_ty = other_ty
+repType (NoteTy _ ty) = repType ty
+repType (ForAllTy _ ty) = repType ty
+repType (TyConApp tc tys) | isNewTyCon tc = repType (newTypeRep tc tys)
+repType other_ty = other_ty
+
+newTypeRep :: TyCon -> [Type] -> Type
+-- The representation type for (T t1 .. tn), where T is a newtype
+-- Looks through one layer only
+newTypeRep tc tys
+ = ASSERT( isNewTyCon tc )
+ case splitFunTy_maybe (applyTys (dataConType (head (tyConDataCons tc))) tys) of
+ Just (rep_ty, _) -> rep_ty
\end{code}
isDataTyCon tc
other -> False
+isNewType :: Type -> Bool
+isNewType ty = case splitTyConApp_maybe ty of
+ Just (tc, ty_args) -> ASSERT( length ty_args == tyConArity tc )
+ isNewTyCon tc
+ other -> False
+
typePrimRep :: Type -> PrimRep
typePrimRep ty = case splitTyConApp_maybe ty of
Just (tc, ty_args) -> tyConPrimRep tc
'-fcse', # CSE must immediately follow a simplification pass, because it relies
# on the no-shadowing invariant. See comments at the top of CSE.lhs
+ '-ffull-laziness', # nofib/spectral/hartel/wang doubles in speed if you
+ # do full laziness late in the day. It only happens
+ # after fusion and other stuff, so the early pass doesn't
+ # catch it. For the record, the redex is
+ # f_el22 (f_el21 r_midblock)
'-ffloat-inwards',
# Case-liberation for -O2. This should be after
\begin{code}
writeChan :: Chan a -> a -> IO ()
-writeChan (Chan read write) val = do
+writeChan (Chan _read write) val = do
new_hole <- newEmptyMVar
old_hole <- takeMVar write
putMVar write new_hole
putMVar old_hole (ChItem val new_hole)
readChan :: Chan a -> IO a
-readChan (Chan read write) = do
+readChan (Chan read _write) = do
read_end <- takeMVar read
(ChItem val new_read_end) <- takeMVar read_end
putMVar read new_read_end
dupChan :: Chan a -> IO (Chan a)
-dupChan (Chan read write) = do
+dupChan (Chan _read write) = do
new_read <- newEmptyMVar
hole <- readMVar write
putMVar new_read hole
return (Chan new_read write)
unGetChan :: Chan a -> a -> IO ()
-unGetChan (Chan read write) val = do
+unGetChan (Chan read _write) val = do
new_read_end <- newEmptyMVar
read_end <- takeMVar read
putMVar new_read_end (ChItem val read_end)
short (_:_:_) _ rest = (errAmbig options optStr,rest)
short (NoArg a :_) [] rest = (Opt a,rest)
short (NoArg a :_) xs rest = (Opt a,('-':xs):rest)
- short (ReqArg f d:_) [] [] = (errReq d optStr,[])
+ short (ReqArg _ d:_) [] [] = (errReq d optStr,[])
short (ReqArg f _:_) [] (r:rest) = (Opt (f r),rest)
short (ReqArg f _:_) xs rest = (Opt (f xs),rest)
short (OptArg f _:_) [] rest = (Opt (f Nothing),rest)
(# s2# , v# #) ->
let w' = word2Int# (int2Word# i# `or#` (int2Word# v# `and#` mask))
in
- case writeIntArray# arr# (n# `quotInt#` 2#) w' s# of
+ case writeIntArray# arr# (n# `quotInt#` 2#) w' s2# of
s2# -> (# s2# , () #)
writeInt32Array (MutableByteArray ixs arr#) n i = ST $ \ s# ->
pid <- forkProcess
case pid of
Nothing -> doTheBusiness
- Just x -> return ()
+ Just _ -> return ()
where
doTheBusiness :: IO ()
doTheBusiness = do
fd_str = "<file descriptor: " ++ show (I# fd#) ++ ">"
fdRead :: Fd -> ByteCount -> IO (String, ByteCount)
-fdRead fd 0 = return ("", 0)
-fdRead fd nbytes = do
+fdRead _fd 0 = return ("", 0)
+fdRead fd nbytes = do
bytes <- allocChars nbytes
rc <- _ccall_ read fd bytes nbytes
case rc of
if str == nullAddr
then do
err <- try (queryTerminal fd)
- either (\err -> syserr "getTerminalName")
- (\succ -> if succ then ioError (IOError Nothing NoSuchThing
+ either (\ _err -> syserr "getTerminalName")
+ (\ succ -> if succ then ioError (IOError Nothing NoSuchThing
"getTerminalName" "no name")
- else ioError (IOError Nothing InappropriateType
+ else ioError (IOError Nothing InappropriateType
"getTerminalName" "not a terminal"))
err
else strcpy str
getAnyProcessStatus :: Bool -> Bool -> IO (Maybe (ProcessID, ProcessStatus))
getAnyProcessStatus block stopped =
getGroupProcessStatus block stopped 1 `catch`
- \ err -> syserr "getAnyProcessStatus"
+ \ _err -> syserr "getAnyProcessStatus"
exitImmediately :: ExitCode -> IO ()
exitImmediately exitcode = do
range (m,n) = [m..n]
{-# INLINE unsafeIndex #-}
- unsafeIndex (m,n) i = fromEnum i - fromEnum m
+ unsafeIndex (m,_n) i = fromEnum i - fromEnum m
index b i | inRange b i = unsafeIndex b i
| otherwise = indexError b i "Char"
range (m,n) = [m..n]
{-# INLINE unsafeIndex #-}
- unsafeIndex (m,n) i = i - m
+ unsafeIndex (m,_n) i = i - m
index b i | inRange b i = unsafeIndex b i
| otherwise = indexError b i "Int"
range (m,n) = [m..n]
{-# INLINE unsafeIndex #-}
- unsafeIndex (m,n) i = fromInteger (i - m)
+ unsafeIndex (m,_n) i = fromInteger (i - m)
index b i | inRange b i = unsafeIndex b i
| otherwise = indexError b i "Integer"
{-# SPECIALISE unsafeRangeSize :: (Int,Int) -> Int #-}
{-# SPECIALISE unsafeRangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
unsafeRangeSize :: (Ix a) => (a,a) -> Int
-unsafeRangeSize b@(l,h) = unsafeIndex b h + 1
+unsafeRangeSize b@(_l,h) = unsafeIndex b h + 1
{-# SPECIALISE rangeSize :: (Int,Int) -> Int #-}
{-# SPECIALISE rangeSize :: ((Int,Int),(Int,Int)) -> Int #-}
rangeSize :: (Ix a) => (a,a) -> Int
-rangeSize b@(l,h) | inRange b h = unsafeIndex b h + 1
- | otherwise = 0
+rangeSize b@(_l,h) | inRange b h = unsafeIndex b h + 1
+ | otherwise = 0
-- Note that the following is NOT right
-- rangeSize (l,h) | l <= h = index b h + 1
-- predicate, respectively; i,e,,
-- partition p xs == (filter p xs, filter (not . p) xs).
partition :: (a -> Bool) -> [a] -> ([a],[a])
-partition p xs = foldr select ([],[]) xs
- where select x (ts,fs) | p x = (x:ts,fs)
- | otherwise = (ts, x:fs)
+{-# INLINE partition #-}
+partition p xs = foldr (select p) ([],[]) xs
+
+select p x (ts,fs) | p x = (x:ts,fs)
+ | otherwise = (ts, x:fs)
\end{code}
@mapAccumL@ behaves like a combination
sequence (m:ms) = do { x <- m; xs <- sequence ms; return (x:xs) }
sequence_ :: Monad m => [m a] -> m ()
+{-# INLINE sequence_ #-}
sequence_ = foldr (>>) (return ())
mapM :: Monad m => (a -> m b) -> [a] -> m [b]
+{-# INLINE mapM #-}
mapM f as = sequence (map f as)
mapM_ :: Monad m => (a -> m b) -> [a] -> m ()
+{-# INLINE mapM_ #-}
mapM_ f as = sequence_ (map f as)
guard :: MonadPlus m => Bool -> m ()
-- This subsumes the list-based concat function.
msum :: MonadPlus m => [m a] -> m a
+{-# INLINE msum #-}
msum = foldr mplus mzero
{-# SPECIALISE (=<<) :: (a -> [b]) -> [a] -> [b] #-}
-----------------------------------------------------------------------
--- these also go better with magic: (//), accum, accumArray
+-- These also go better with magic: (//), accum, accumArray
+-- *** NB *** We INLINE them all so that their foldr's get to the call site
+{-# INLINE (//) #-}
old_array // ivs
= runST (do
-- copy the old array:
)
fill_it_in :: Ix ix => MutableArray s ix elt -> [(ix, elt)] -> ST s ()
-fill_it_in arr lst
- = foldr fill_one_in (return ()) lst
- where -- **** STRICT **** (but that's OK...)
- fill_one_in (i, v) rst
- = writeArray arr i v >> rst
+{-# INLINE fill_it_in #-}
+fill_it_in arr lst = foldr (fill_one_in arr) (return ()) lst
+ -- **** STRICT **** (but that's OK...)
+
+fill_one_in arr (i, v) rst = writeArray arr i v >> rst
zap_with_f :: Ix ix => (elt -> elt2 -> elt) -> MutableArray s ix elt -> [(ix,elt2)] -> ST s ()
-- zap_with_f: reads an elem out first, then uses "f" on that and the new value
+{-# INLINE zap_with_f #-}
zap_with_f f arr lst
- = foldr zap_one (return ()) lst
- where
- zap_one (i, new_v) rst = do
- old_v <- readArray arr i
+ = foldr (zap_one f arr) (return ()) lst
+
+zap_one f arr (i, new_v) rst = do
+ old_v <- readArray arr i
writeArray arr i (f old_v new_v)
rst
+{-# INLINE accum #-}
accum f old_array ivs
= runST (do
-- copy the old array:
freezeArray arr
)
+{-# INLINE accumArray #-}
accumArray f zero ixs ivs
= runST (do
- arr# <- newArray ixs zero
- zap_with_f f arr# ivs
- freezeArray arr#
+ arr <- newArray ixs zero
+ zap_with_f f arr ivs
+ freezeArray arr
)
\end{code}
-- be defined for an instance of Ord
| otherwise = GT
- x <= y = case compare x y of { GT -> False; other -> True }
- x < y = case compare x y of { LT -> True; other -> False }
- x >= y = case compare x y of { LT -> False; other -> True }
- x > y = case compare x y of { GT -> True; other -> False }
+ x <= y = case compare x y of { GT -> False; _other -> True }
+ x < y = case compare x y of { LT -> True; _other -> False }
+ x >= y = case compare x y of { LT -> False; _other -> True }
+ x > y = case compare x y of { GT -> True; _other -> False }
-- These two default methods use '>' rather than compare
-- because the latter is often more expensive
-- to avoid weird names like con2tag_[]#
instance (Eq a) => Eq [a] where
+ {-# SPECIALISE instance Eq [Char] #-}
[] == [] = True
(x:xs) == (y:ys) = x == y && xs == ys
_xs == _ys = False
xs /= ys = if (xs == ys) then False else True
instance (Ord a) => Ord [a] where
+ {-# SPECIALISE instance Ord [Char] #-}
a < b = case compare a b of { LT -> True; EQ -> False; GT -> False }
a <= b = case compare a b of { LT -> True; EQ -> True; GT -> False }
a >= b = case compare a b of { LT -> False; EQ -> True; GT -> True }
maxBound = ()
instance Enum () where
- succ x = error "Prelude.Enum.().succ: bad argment"
- pred x = error "Prelude.Enum.().pred: bad argument"
+ succ _ = error "Prelude.Enum.().succ: bad argment"
+ pred _ = error "Prelude.Enum.().pred: bad argument"
toEnum x | x == zeroInt = ()
| otherwise = error "Prelude.Enum.().toEnum: bad argument"
toEnum n | n == zeroInt = LT
| n == oneInt = EQ
| n == twoInt = GT
- toEnum n = error "Prelude.Enum.Ordering.toEnum: bad argment"
+ toEnum _ = error "Prelude.Enum.Ordering.toEnum: bad argment"
fromEnum LT = zeroInt
fromEnum EQ = oneInt
maxBound = '\255'
instance Enum Char where
- succ c@(C# c#)
+ succ (C# c#)
| not (ord# c# ==# 255#) = C# (chr# (ord# c# +# 1#))
| otherwise = error ("Prelude.Enum.Char.succ: bad argument")
- pred c@(C# c#)
+ pred (C# c#)
| not (ord# c# ==# 0#) = C# (chr# (ord# c# -# 1#))
| otherwise = error ("Prelude.Enum.Char.pred: bad argument")
ClosedHandle -> ioe_closedHandle fun handle
SemiClosedHandle -> ioe_closedHandle fun handle
_ -> act handle_
- where
- not_rw_error =
- IOError (Just handle) IllegalOperation fun
- ("handle is not open for reading or writing")
wantSeekableHandle :: String -> Handle -> (Handle__ -> IO a) -> IO a
wantSeekableHandle fun handle act =
-- iterate f x == [x, f x, f (f x), ...]
iterate :: (a -> a) -> a -> [a]
{-# INLINE iterate #-}
-iterate f x = build (\c n -> iterateFB c f x)
+iterate f x = build (\c _n -> iterateFB c f x)
iterateFB c f x = x `c` iterateFB c f (f x)
-- repeat x is an infinite list, with x the value of every element.
repeat :: a -> [a]
{-# INLINE repeat #-}
-repeat x = build (\c n -> repeatFB c x)
+repeat x = build (\c _n -> repeatFB c x)
repeatFB c x = xs where xs = x `c` xs
repeatList x = xs where xs = x : xs
%*********************************************************
\begin{code}
-foldr2 k z [] ys = z
-foldr2 k z xs [] = z
+foldr2 _k z [] _ys = z
+foldr2 _k z _xs [] = z
foldr2 k z (x:xs) (y:ys) = k x y (foldr2 k z xs ys)
-foldr2_left k z x r [] = z
-foldr2_left k z x r (y:ys) = k x y (r ys)
+foldr2_left _k z _x _r [] = z
+foldr2_left k _z x r (y:ys) = k x y (r ys)
-foldr2_right k z y r [] = z
-foldr2_right k z y r (x:xs) = k x y (r xs)
+foldr2_right _k z _y _r [] = z
+foldr2_right k _z y r (x:xs) = k x y (r xs)
-- foldr2 k z xs ys = foldr (foldr2_left k z) (\_ -> z) xs ys
-- foldr2 k z xs ys = foldr (foldr2_right k z) (\_ -> z) ys xs
zipWithList :: (a->b->c) -> [a] -> [b] -> [c]
zipWithList f (a:as) (b:bs) = f a b : zipWithList f as bs
-zipWithList f _ _ = []
+zipWithList _ _ _ = []
{-# RULES
"zipWithList" forall f. foldr2 (zipWithFB (:) f) [] = zipWithList f
-- unzip transforms a list of pairs into a pair of lists.
unzip :: [(a,b)] -> ([a],[b])
+{-# INLINE unzip #-}
unzip = foldr (\(a,b) ~(as,bs) -> (a:as,b:bs)) ([],[])
unzip3 :: [(a,b,c)] -> ([a],[b],[c])
+{-# INLINE unzip3 #-}
unzip3 = foldr (\(a,b,c) ~(as,bs,cs) -> (a:as,b:bs,c:cs))
([],[],[])
\end{code}
}
toBig (S# i) = case int2Integer# i of { (# s, d #) -> J# s d }
-toBig i@(J# s d) = i
+toBig i@(J# _ _) = i
instance Num Integer where
(+) i1@(S# i) i2@(S# j)
= case addIntC# i j of { (# r, c #) ->
if c ==# 0# then S# r
else toBig i1 + toBig i2 }
- (+) i1@(J# s d) i2@(S# i) = i1 + toBig i2
- (+) i1@(S# i) i2@(J# s d) = toBig i1 + i2
+ (+) i1@(J# _ _) i2@(S# _) = i1 + toBig i2
+ (+) i1@(S# _) i2@(J# _ _) = toBig i1 + i2
(+) (J# s1 d1) (J# s2 d2)
= case plusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
= case subIntC# i j of { (# r, c #) ->
if c ==# 0# then S# r
else toBig i1 - toBig i2 }
- (-) i1@(J# s d) i2@(S# i) = i1 - toBig i2
- (-) i1@(S# i) i2@(J# s d) = toBig i1 - i2
+ (-) i1@(J# _ _) i2@(S# _) = i1 - toBig i2
+ (-) i1@(S# _) i2@(J# _ _) = toBig i1 - i2
(-) (J# s1 d1) (J# s2 d2)
= case minusInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
= case mulIntC# i j of { (# r, c #) ->
if c ==# 0# then S# r
else toBig i1 * toBig i2 }
- (*) i1@(J# s d) i2@(S# i) = i1 * toBig i2
- (*) i1@(S# i) i2@(J# s d) = toBig i1 * i2
+ (*) i1@(J# _ _) i2@(S# _) = i1 * toBig i2
+ (*) i1@(S# _) i2@(J# _ _) = toBig i1 * i2
(*) (J# s1 d1) (J# s2 d2)
= case timesInteger# s1 d1 s2 d2 of (# s, d #) -> J# s d
- negate i@(S# (-2147483648#)) = 2147483648
+ negate (S# (-2147483648#)) = 2147483648
negate (S# i) = S# (negateInt# i)
negate (J# s d) = J# (negateInt# s) d
-- a `quot` b returns a small integer if a is small.
quotRem (S# i) (S# j)
= case quotRem (I# i) (I# j) of ( I# i, I# j ) -> ( S# i, S# j)
- quotRem i1@(J# s d) i2@(S# i) = quotRem i1 (toBig i2)
- quotRem i1@(S# i) i2@(J# s d) = quotRem (toBig i1) i2
+ quotRem i1@(J# _ _) i2@(S# _) = quotRem i1 (toBig i2)
+ quotRem i1@(S# _) i2@(J# _ _) = quotRem (toBig i1) i2
quotRem (J# s1 d1) (J# s2 d2)
= case (quotRemInteger# s1 d1 s2 d2) of
(# s3, d3, s4, d4 #)
{-# INLINE enumFromThen #-}
{-# INLINE enumFromTo #-}
{-# INLINE enumFromThenTo #-}
- enumFrom x = build (\c n -> enumDeltaIntegerFB c x 1)
- enumFromThen x y = build (\c n -> enumDeltaIntegerFB c x (y-x))
+ enumFrom x = build (\c _ -> enumDeltaIntegerFB c x 1)
+ enumFromThen x y = build (\c _ -> enumDeltaIntegerFB c x (y-x))
enumFromTo x lim = build (\c n -> enumDeltaToIntegerFB c n x 1 lim)
enumFromThenTo x y lim = build (\c n -> enumDeltaToIntegerFB c n x (y-x) lim)
showsPrec p n = showSignedInt p n
instance Show a => Show (Maybe a) where
- showsPrec p Nothing = showString "Nothing"
- showsPrec p (Just x) = showString "Just " . shows x
+ showsPrec _p Nothing = showString "Nothing"
+ showsPrec _p (Just x) = showString "Just " . shows x
-- Not sure I have the priorities right here
instance (Show a, Show b) => Show (Either a b) where
- showsPrec p (Left a) = showString "Left " . shows a
- showsPrec p (Right b) = showString "Right " . shows b
+ showsPrec _p (Left a) = showString "Left " . shows a
+ showsPrec _p (Right b) = showString "Right " . shows b
-- Not sure I have the priorities right here
\end{code}
showSignedInt p s2
instance Read StdGen where
- readsPrec p = \ r ->
+ readsPrec _p = \ r ->
case try_read r of
r@[_] -> r
_ -> [stdFromString r] -- because it shouldn't ever fail.
s2'' = if s2' < 0 then s2' + 2147483399 else s2'
stdSplit :: StdGen -> (StdGen, StdGen)
-stdSplit std@(StdGen s1 s2) = (std, unsafePerformIO (mkStdRNG (fromInt s1)))
+stdSplit std@(StdGen s1 _) = (std, unsafePerformIO (mkStdRNG (fromInt s1)))
\end{code}