From 9d38678ea60ff32f756390a30c659daa22c98c93 Mon Sep 17 00:00:00 2001 From: simonpj <unknown> Date: Tue, 6 Jul 1999 16:46:12 +0000 Subject: [PATCH] [project @ 1999-07-06 16:45:31 by simonpj] All Simon's recent tuning changes. Rough summary follows: * Fix Kevin Atkinson's cant-find-instance bug. Turns out that Rename.slurpSourceRefs needs to repeatedly call getImportedInstDecls, and then go back to slurping source-refs. Comments with Rename.slurpSourceRefs. * Add a case to Simplify.mkDupableAlt for the quite-common case where there's a very simple alternative, in which case there's no point in creating a join-point binding. * Fix CoreUtils.exprOkForSpeculation so that it returns True of (==# a# b#). This lack meant that case ==# a# b# of { True -> x; False -> x } was not simplifying * Make float-out dump bindings at the top of a function argument, as at the top of a let(rec) rhs. See notes with FloatOut.floatRhs * Make the ArgOf case of mkDupableAlt generate a OneShot lambda. This gave a noticeable boost to spectral/boyer2 * Reduce the number of coerces, using worker/wrapper stuff. The main idea is in WwLib.mkWWcoerce. The gloss is that we must do the w/w split even for small non-recursive things. See notes with WorkWrap.tryWw. * This further complicated getWorkerId, so I finally bit the bullet and make the workerInfo field of the IdInfo work properly, including under substitutions. Death to getWorkerId. Kevin Glynn will be happy. * Make all lambdas over realWorldStatePrimTy into one-shot lambdas. This is a GROSS HACK. * Also make the occurrence analyser aware of one-shot lambdas. * Make various Prelude things into INLINE, so that foldr doesn't get inlined in their body, so that the caller gets the benefit of fusion. Notably in PrelArr.lhs. --- ghc/compiler/basicTypes/Id.lhs | 17 ++- ghc/compiler/basicTypes/IdInfo.lhs | 15 ++- ghc/compiler/coreSyn/CoreSyn.lhs | 4 +- ghc/compiler/coreSyn/CoreTidy.lhs | 27 +++-- ghc/compiler/coreSyn/CoreUnfold.lhs | 31 ++--- ghc/compiler/coreSyn/CoreUtils.lhs | 104 ++++++++++++----- ghc/compiler/coreSyn/PprCore.lhs | 4 +- ghc/compiler/coreSyn/Subst.lhs | 35 +++++- ghc/compiler/main/MkIface.lhs | 26 ++--- ghc/compiler/rename/ParseIface.y | 24 +--- ghc/compiler/rename/Rename.lhs | 102 +++++++++-------- ghc/compiler/rename/RnIfaces.lhs | 14 ++- ghc/compiler/simplCore/FloatOut.lhs | 52 +++++---- ghc/compiler/simplCore/OccurAnal.lhs | 18 +-- ghc/compiler/simplCore/SetLevels.lhs | 12 +- ghc/compiler/simplCore/SimplUtils.lhs | 23 ++-- ghc/compiler/simplCore/Simplify.lhs | 90 ++++++++++----- ghc/compiler/specialise/Rules.lhs | 14 ++- ghc/compiler/stranal/WorkWrap.lhs | 52 +++++++-- ghc/compiler/stranal/WwLib.lhs | 159 +++++++++++++++++--------- ghc/compiler/typecheck/TcGenDeriv.lhs | 8 +- ghc/compiler/typecheck/TcIfaceSig.lhs | 9 +- ghc/compiler/types/Type.lhs | 36 ++++-- ghc/driver/ghc.lprl | 5 + ghc/lib/concurrent/Channel.lhs | 8 +- ghc/lib/exts/GetOpt.lhs | 2 +- ghc/lib/exts/MutableArray.lhs | 2 +- ghc/lib/posix/Posix.lhs | 2 +- ghc/lib/posix/PosixIO.lhs | 4 +- ghc/lib/posix/PosixProcEnv.lhs | 6 +- ghc/lib/posix/PosixProcPrim.lhs | 2 +- ghc/lib/std/Ix.lhs | 12 +- ghc/lib/std/List.lhs | 8 +- ghc/lib/std/Monad.lhs | 4 + ghc/lib/std/PrelArr.lhs | 31 ++--- ghc/lib/std/PrelBase.lhs | 10 +- ghc/lib/std/PrelEnum.lhs | 10 +- ghc/lib/std/PrelHandle.lhs | 4 - ghc/lib/std/PrelList.lhs | 20 ++-- ghc/lib/std/PrelNum.lhs | 24 ++-- ghc/lib/std/PrelShow.lhs | 8 +- ghc/lib/std/Random.lhs | 4 +- 42 files changed, 646 insertions(+), 396 deletions(-) diff --git a/ghc/compiler/basicTypes/Id.lhs b/ghc/compiler/basicTypes/Id.lhs index 3ba8763b5e2a..1c8e02619761 100644 --- a/ghc/compiler/basicTypes/Id.lhs +++ b/ghc/compiler/basicTypes/Id.lhs @@ -83,6 +83,7 @@ import Name ( Name, OccName, import Const ( Con(..) ) import PrimRep ( PrimRep ) import PrimOp ( PrimOp ) +import TysPrim ( realWorldStatePrimTy ) import FieldLabel ( FieldLabel(..) ) import SrcLoc ( SrcLoc ) import Unique ( Unique, mkBuiltinUnique, getBuiltinUniques ) @@ -371,7 +372,21 @@ idMustBeINLINEd id = case getInlinePragma id of 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 diff --git a/ghc/compiler/basicTypes/IdInfo.lhs b/ghc/compiler/basicTypes/IdInfo.lhs index d5e2ccc4e89b..2c36363b4e0d 100644 --- a/ghc/compiler/basicTypes/IdInfo.lhs +++ b/ghc/compiler/basicTypes/IdInfo.lhs @@ -19,7 +19,7 @@ module IdInfo ( -- Arity ArityInfo(..), - exactArity, atLeastArity, unknownArity, + exactArity, atLeastArity, unknownArity, hasArity, arityInfo, setArityInfo, ppArityInfo, arityLowerBound, -- Strictness @@ -31,7 +31,7 @@ module IdInfo ( -- Worker WorkerInfo, workerExists, - workerInfo, setWorkerInfo, + workerInfo, setWorkerInfo, ppWorkerInfo, -- Unfolding unfoldingInfo, setUnfoldingInfo, @@ -267,6 +267,9 @@ arityLowerBound UnknownArity = 0 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] @@ -409,10 +412,10 @@ type WorkerInfo = Maybe Id {- 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 @@ -497,6 +500,7 @@ substitution to be correct. (They get pinned back on separately.) \begin{code} zapFragileIdInfo :: IdInfo -> Maybe IdInfo zapFragileIdInfo info@(IdInfo {inlinePragInfo = inline_prag, + workerInfo = wrkr, specInfo = rules, unfoldingInfo = unfolding}) | not is_fragile_inline_prag @@ -508,6 +512,8 @@ zapFragileIdInfo info@(IdInfo {inlinePragInfo = 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 @@ -518,6 +524,7 @@ zapFragileIdInfo info@(IdInfo {inlinePragInfo = inline_prag, | otherwise = Just (info {inlinePragInfo = safe_inline_prag, + workerInfo = noWorkerInfo, specInfo = emptyCoreRules, unfoldingInfo = noUnfolding}) diff --git a/ghc/compiler/coreSyn/CoreSyn.lhs b/ghc/compiler/coreSyn/CoreSyn.lhs index 285ecc2724a3..e59fec1b7c53 100644 --- a/ghc/compiler/coreSyn/CoreSyn.lhs +++ b/ghc/compiler/coreSyn/CoreSyn.lhs @@ -10,7 +10,7 @@ module CoreSyn ( TaggedExpr, TaggedAlt, TaggedBind, TaggedArg, mkLets, mkLams, - mkApps, mkTyApps, mkValApps, + mkApps, mkTyApps, mkValApps, mkVarApps, mkLit, mkStringLit, mkConApp, mkPrimApp, mkNote, bindNonRec, mkIfThenElse, varToCoreExpr, @@ -171,10 +171,12 @@ type TaggedAlt t = Alt (Tagged t) 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 diff --git a/ghc/compiler/coreSyn/CoreTidy.lhs b/ghc/compiler/coreSyn/CoreTidy.lhs index bec784c7fcde..27843e820bad 100644 --- a/ghc/compiler/coreSyn/CoreTidy.lhs +++ b/ghc/compiler/coreSyn/CoreTidy.lhs @@ -27,7 +27,8 @@ import Id ( idType, idInfo, idName, ) import IdInfo ( specInfo, setSpecInfo, inlinePragInfo, setInlinePragInfo, InlinePragInfo(..), - setUnfoldingInfo, setDemandInfo + setUnfoldingInfo, setDemandInfo, + workerInfo, setWorkerInfo ) import Demand ( wwLazy ) import Name ( getOccName, tidyTopName, mkLocalName, isLocallyDefined ) @@ -101,7 +102,7 @@ tidyBind :: Maybe Module -- (Just m) for top level, Nothing for nested -> (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') @@ -116,7 +117,7 @@ tidyBind maybe_mod env (Rec pairs) -- 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')) @@ -154,8 +155,8 @@ tidyVarOcc (_, var_env) v = case lookupVarEnv var_env v of \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} @@ -198,14 +199,18 @@ tidyId env@(tidy_env, var_env) id 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 @@ -220,7 +225,7 @@ tidyTopId mod env@(tidy_env, var_env) id -- The latter two are to avoid space leaks tidyIdInfo env info - = info4 + = info5 where rules = specInfo info @@ -234,6 +239,10 @@ tidyIdInfo env 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) diff --git a/ghc/compiler/coreSyn/CoreUnfold.lhs b/ghc/compiler/coreSyn/CoreUnfold.lhs index 6fd0fd9b4db1..f27289ec0e92 100644 --- a/ghc/compiler/coreSyn/CoreUnfold.lhs +++ b/ghc/compiler/coreSyn/CoreUnfold.lhs @@ -20,7 +20,7 @@ module CoreUnfold ( mkOtherCon, otherCons, unfoldingTemplate, maybeUnfoldingTemplate, isEvaldUnfolding, isCheapUnfolding, - hasUnfolding, + hasUnfolding, hasSomeUnfolding, couldBeSmallEnoughToInline, certainlySmallEnoughToInline, @@ -471,12 +471,12 @@ so we can inline if it occurs once, or is small 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 ; @@ -487,8 +487,7 @@ callSiteInline black_listed inline_call id args interesting_cont | 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 @@ -511,7 +510,7 @@ callSiteInline black_listed inline_call id args interesting_cont 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 @@ -539,11 +538,10 @@ callSiteInline black_listed inline_call id args interesting_cont 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. @@ -575,17 +573,6 @@ callSiteInline black_listed inline_call id args interesting_cont 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) diff --git a/ghc/compiler/coreSyn/CoreUtils.lhs b/ghc/compiler/coreSyn/CoreUtils.lhs index bc6b37611be5..9b9b03c85ee7 100644 --- a/ghc/compiler/coreSyn/CoreUtils.lhs +++ b/ghc/compiler/coreSyn/CoreUtils.lhs @@ -7,9 +7,10 @@ module CoreUtils ( coreExprType, coreAltsType, - exprIsBottom, exprIsDupable, exprIsTrivial, exprIsCheap, exprIsValue, + exprIsBottom, exprIsDupable, exprIsTrivial, exprIsCheap, + exprIsValue, exprOkForSpeculation, exprIsBig, hashExpr, - exprArity, + exprArity, exprGenerousArity, cheapEqExpr, eqExpr, applyTypeToArgs ) where @@ -192,13 +193,6 @@ exprIsCheap (Var _) = True 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 @@ -224,9 +218,20 @@ isPap (Var f) n_val_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 ==> @@ -240,26 +245,17 @@ side effects, and can't diverge or raise an exception. \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} @@ -304,9 +300,63 @@ exprIsValue e@(App _ _) = case collectArgs e of \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} diff --git a/ghc/compiler/coreSyn/PprCore.lhs b/ghc/compiler/coreSyn/PprCore.lhs index 3f3b5a073c26..e4f2d7bb6088 100644 --- a/ghc/compiler/coreSyn/PprCore.lhs +++ b/ghc/compiler/coreSyn/PprCore.lhs @@ -24,7 +24,8 @@ import IdInfo ( IdInfo, 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 ) @@ -344,6 +345,7 @@ ppIdInfo info ppFlavourInfo (flavourInfo info), ppArityInfo a, ppUpdateInfo u, + ppWorkerInfo (workerInfo info), ppStrictnessInfo s, ppr d, ppCafInfo c, diff --git a/ghc/compiler/coreSyn/Subst.lhs b/ghc/compiler/coreSyn/Subst.lhs index b3f93eac2118..64d4d502f683 100644 --- a/ghc/compiler/coreSyn/Subst.lhs +++ b/ghc/compiler/coreSyn/Subst.lhs @@ -26,12 +26,11 @@ module Subst ( substTy, substTheta, -- Expression stuff - substExpr, substRules + substExpr, substIdInfo ) where #include "HsVersions.h" - import CoreSyn ( Expr(..), Bind(..), Note(..), CoreExpr, CoreBndr, CoreRules(..), CoreRule(..), emptyCoreRules, isEmptyCoreRules ) @@ -43,7 +42,10 @@ import VarSet 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 @@ -400,11 +402,36 @@ substAndCloneId subst@(Subst in_scope env) us old_id %************************************************************************ %* * -\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) diff --git a/ghc/compiler/main/MkIface.lhs b/ghc/compiler/main/MkIface.lhs index 0766eeaa2049..2fec609e8568 100644 --- a/ghc/compiler/main/MkIface.lhs +++ b/ghc/compiler/main/MkIface.lhs @@ -19,7 +19,6 @@ import RnMonad import RnEnv ( availName ) import TcInstUtil ( InstInfo(..) ) -import WorkWrap ( getWorkerId ) import CmdLineOpts import Id ( Id, idType, idInfo, omitIfaceSigForId, isUserExportedId, @@ -30,10 +29,10 @@ import VarSet 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 ) @@ -304,7 +303,8 @@ ifaceId get_idinfo needed_ids is_rec id rhs arity_pretty, caf_pretty, cpr_pretty, - strict_pretty, + strict_pretty, + wrkr_pretty, unfold_pretty, ptext SLIT("##-}")] @@ -317,21 +317,17 @@ ifaceId get_idinfo needed_ids is_rec id rhs ------------ 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 diff --git a/ghc/compiler/rename/ParseIface.y b/ghc/compiler/rename/ParseIface.y index 5d58b407a6e1..6df655d7abd0 100644 --- a/ghc/compiler/rename/ParseIface.y +++ b/ghc/compiler/rename/ParseIface.y @@ -576,31 +576,15 @@ akind :: { Kind } 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 } diff --git a/ghc/compiler/rename/Rename.lhs b/ghc/compiler/rename/Rename.lhs index ca22b19a0ef5..baf7b300dde4 100644 --- a/ghc/compiler/rename/Rename.lhs +++ b/ghc/compiler/rename/Rename.lhs @@ -240,47 +240,69 @@ slurpImpDecls source_fvs -- 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 @@ -297,39 +319,19 @@ slurpSourceRefs source_binders source_fvs 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 diff --git a/ghc/compiler/rename/RnIfaces.lhs b/ghc/compiler/rename/RnIfaces.lhs index f7276b8ba745..c5018a4c8177 100644 --- a/ghc/compiler/rename/RnIfaces.lhs +++ b/ghc/compiler/rename/RnIfaces.lhs @@ -537,10 +537,7 @@ getInterfaceExports mod_name from \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 @@ -560,8 +557,8 @@ getImportedInstDecls gates 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 @@ -572,6 +569,11 @@ getImportedInstDecls 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 -> diff --git a/ghc/compiler/simplCore/FloatOut.lhs b/ghc/compiler/simplCore/FloatOut.lhs index e4e47f757e83..d41f3d91e9eb 100644 --- a/ghc/compiler/simplCore/FloatOut.lhs +++ b/ghc/compiler/simplCore/FloatOut.lhs @@ -128,15 +128,11 @@ floatBind :: IdEnv Level -> (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) -> @@ -172,13 +168,9 @@ floatBind env lvl bind@(Rec 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} %************************************************************************ @@ -188,20 +180,32 @@ floatBind env lvl bind@(Rec pairs) %************************************************************************ \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) @@ -355,8 +359,10 @@ partitionByMajorLevel, partitionByLevel 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 diff --git a/ghc/compiler/simplCore/OccurAnal.lhs b/ghc/compiler/simplCore/OccurAnal.lhs index 87927ece4821..e137536997bf 100644 --- a/ghc/compiler/simplCore/OccurAnal.lhs +++ b/ghc/compiler/simplCore/OccurAnal.lhs @@ -25,7 +25,7 @@ import CoreSyn import CoreFVs ( idRuleVars ) import CoreUtils ( exprIsTrivial ) import Const ( Con(..), Literal(..) ) -import Id ( isSpecPragmaId, +import Id ( isSpecPragmaId, isOneShotLambda, getInlinePragma, setInlinePragma, isExportedId, modifyIdInfo, idInfo, getIdSpecialisation, @@ -635,7 +635,7 @@ occAnal env expr@(Lam _ _) 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') -> @@ -764,11 +764,15 @@ addNewCand (OccEnv ifun cands ctxt) id 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 [] diff --git a/ghc/compiler/simplCore/SetLevels.lhs b/ghc/compiler/simplCore/SetLevels.lhs index 2937890e93ba..e74525d0349b 100644 --- a/ghc/compiler/simplCore/SetLevels.lhs +++ b/ghc/compiler/simplCore/SetLevels.lhs @@ -663,7 +663,7 @@ cloneVar NotTopLevel (lvl_env, subst_env) v lvl 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 @@ -672,20 +672,14 @@ cloneVar NotTopLevel (lvl_env, subst_env) v lvl 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} diff --git a/ghc/compiler/simplCore/SimplUtils.lhs b/ghc/compiler/simplCore/SimplUtils.lhs index 4ef7937e36b6..7ce7e2770f18 100644 --- a/ghc/compiler/simplCore/SimplUtils.lhs +++ b/ghc/compiler/simplCore/SimplUtils.lhs @@ -18,7 +18,7 @@ import BinderInfo 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, @@ -287,7 +287,7 @@ where (in both cases) N is a NORMAL FORM (i.e. no redexes anywhere) 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; @@ -314,9 +314,7 @@ tryEtaExpansion rhs (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) @@ -335,7 +333,7 @@ tryEtaExpansion rhs 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 @@ -349,8 +347,9 @@ tryEtaExpansion rhs -- (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, @@ -360,11 +359,11 @@ tryEtaExpansion rhs -- \ 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} diff --git a/ghc/compiler/simplCore/Simplify.lhs b/ghc/compiler/simplCore/Simplify.lhs index 6c365b73485b..bb7fc9e919b2 100644 --- a/ghc/compiler/simplCore/Simplify.lhs +++ b/ghc/compiler/simplCore/Simplify.lhs @@ -24,14 +24,14 @@ import Id ( Id, idType, idInfo, idUnique, 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 ) @@ -43,7 +43,7 @@ import Name ( isLocallyDefined ) 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, @@ -56,7 +56,7 @@ import Type ( Type, mkTyVarTy, mkTyVarTys, isUnLiftedType, 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 ) @@ -531,25 +531,23 @@ completeBinding old_bndr new_bndr new_rhs thing_inside | 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) @@ -741,6 +739,8 @@ completeCall black_list_fn in_scope var cont (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 @@ -748,7 +748,7 @@ completeCall black_list_fn in_scope var 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 @@ -757,6 +757,22 @@ completeCall black_list_fn in_scope var cont 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 { .... } @@ -976,8 +992,15 @@ rebuild scrut (Select _ bndr alts se cont) 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 @@ -1349,7 +1372,7 @@ mkDupableCont join_arg_ty (ArgOf _ cont_ty cont_fn) thing_inside 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 @@ -1397,7 +1420,22 @@ mkDupableCont ty (Select _ case_bndr alts se cont) thing_inside 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' -> diff --git a/ghc/compiler/specialise/Rules.lhs b/ghc/compiler/specialise/Rules.lhs index 99da2e2d705b..8406b0a49876 100644 --- a/ghc/compiler/specialise/Rules.lhs +++ b/ghc/compiler/specialise/Rules.lhs @@ -159,7 +159,17 @@ matchRule in_scope (Rule rn tpl_vars tpl_args rhs) args -- 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) @@ -188,6 +198,7 @@ matchRule in_scope (Rule rn tpl_vars tpl_args rhs) args Nothing -> Nothing eta_complete other vars = Nothing +-} ----------------------- mk_result_args subst vs = map go vs @@ -198,6 +209,7 @@ matchRule in_scope (Rule rn tpl_vars tpl_args rhs) args Just (DoneTy ty) -> Type ty -- Substitution should bind them all! + zapOccInfo bndr | isTyVar bndr = bndr | otherwise = maybeModifyIdInfo zapLamIdInfo bndr \end{code} diff --git a/ghc/compiler/stranal/WorkWrap.lhs b/ghc/compiler/stranal/WorkWrap.lhs index 472cfd9f0165..7a95e55cded6 100644 --- a/ghc/compiler/stranal/WorkWrap.lhs +++ b/ghc/compiler/stranal/WorkWrap.lhs @@ -4,7 +4,7 @@ \section[WorkWrap]{Worker/wrapper-generating back-end of strictness analyser} \begin{code} -module WorkWrap ( wwTopBinds, getWorkerId ) where +module WorkWrap ( wwTopBinds ) where #include "HsVersions.h" @@ -22,7 +22,7 @@ import Id ( Id, getIdStrictness, setIdArity, setIdStrictness, setIdWorkerInfo, getIdCprInfo ) import VarSet -import Type ( splitAlgTyConApp_maybe ) +import Type ( isNewType ) import IdInfo ( mkStrictnessInfo, noStrictnessInfo, StrictnessInfo(..), CprInfo(..), exactArity ) @@ -205,20 +205,40 @@ tryWW :: Bool -- True <=> a non-recursive binding -- 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) -> @@ -245,7 +265,7 @@ tryWW non_rec fn_id rhs 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 @@ -264,13 +284,20 @@ tryWW non_rec fn_id rhs 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. @@ -313,4 +340,5 @@ getWorkerId wrap_id wrapper_fn work_id_try2 (App fn _) = work_id_try2 fn work_id_try2 (Var work_id) = [work_id] work_id_try2 other = [] +-} \end{code} diff --git a/ghc/compiler/stranal/WwLib.lhs b/ghc/compiler/stranal/WwLib.lhs index 7d68fc97ba46..4eefd47a1907 100644 --- a/ghc/compiler/stranal/WwLib.lhs +++ b/ghc/compiler/stranal/WwLib.lhs @@ -26,7 +26,8 @@ import TysPrim ( realWorldStatePrimTy ) 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, @@ -270,89 +271,130 @@ mkWwBodies :: [TyVar] -> [Id] -> Type -- Original fn args and body type 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) @@ -370,15 +412,20 @@ mkWW (arg : ds) 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 @@ -613,6 +660,4 @@ mk_unboxed_tuple contents map fst contents), mkTyConApp (unboxedTupleTyCon (length contents)) (map snd contents)) - - \end{code} diff --git a/ghc/compiler/typecheck/TcGenDeriv.lhs b/ghc/compiler/typecheck/TcGenDeriv.lhs index a95ffe91a725..4937d47d7326 100644 --- a/ghc/compiler/typecheck/TcGenDeriv.lhs +++ b/ghc/compiler/typecheck/TcGenDeriv.lhs @@ -61,7 +61,7 @@ import TysPrim ( charPrimTy, intPrimTy, wordPrimTy, addrPrimTy, 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 ) @@ -1068,6 +1068,12 @@ isLRAssoc fixs_assoc nm = 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} diff --git a/ghc/compiler/typecheck/TcIfaceSig.lhs b/ghc/compiler/typecheck/TcIfaceSig.lhs index 0e15147dd9ce..556980d486ab 100644 --- a/ghc/compiler/typecheck/TcIfaceSig.lhs +++ b/ghc/compiler/typecheck/TcIfaceSig.lhs @@ -114,7 +114,7 @@ tcIdInfo unf_env name ty info info_ins \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 @@ -131,9 +131,10 @@ tcWorkerInfo unf_env ty info worker_name 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} diff --git a/ghc/compiler/types/Type.lhs b/ghc/compiler/types/Type.lhs index a7b6572e4d1d..d77827790a12 100644 --- a/ghc/compiler/types/Type.lhs +++ b/ghc/compiler/types/Type.lhs @@ -25,14 +25,15 @@ module Type ( 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, @@ -45,7 +46,7 @@ module Type ( mkSigmaTy, splitSigmaTy, -- Lifting and boxity - isUnLiftedType, isUnboxedType, isUnboxedTupleType, isAlgType, isDataType, + isUnLiftedType, isUnboxedType, isUnboxedTupleType, isAlgType, isDataType, isNewType, typePrimRep, -- Free variables @@ -450,6 +451,11 @@ funResultTy :: Type -> Type 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} @@ -579,12 +585,18 @@ interested in newtypes anymore. \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} @@ -985,6 +997,12 @@ isDataType ty = case splitTyConApp_maybe ty of 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 diff --git a/ghc/driver/ghc.lprl b/ghc/driver/ghc.lprl index a05f14755b73..5e93214df655 100644 --- a/ghc/driver/ghc.lprl +++ b/ghc/driver/ghc.lprl @@ -775,6 +775,11 @@ sub setupOptimiseFlags { '-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 diff --git a/ghc/lib/concurrent/Channel.lhs b/ghc/lib/concurrent/Channel.lhs index fca29df8249f..18dd20e57c95 100644 --- a/ghc/lib/concurrent/Channel.lhs +++ b/ghc/lib/concurrent/Channel.lhs @@ -70,14 +70,14 @@ new hole. \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 @@ -85,14 +85,14 @@ readChan (Chan read write) = do 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) diff --git a/ghc/lib/exts/GetOpt.lhs b/ghc/lib/exts/GetOpt.lhs index f8c464695310..2a934dfc7f6c 100644 --- a/ghc/lib/exts/GetOpt.lhs +++ b/ghc/lib/exts/GetOpt.lhs @@ -125,7 +125,7 @@ shortOpt x xs rest optDescr = short ads xs rest 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) diff --git a/ghc/lib/exts/MutableArray.lhs b/ghc/lib/exts/MutableArray.lhs index 205d71c7b5ea..7c8698228c24 100644 --- a/ghc/lib/exts/MutableArray.lhs +++ b/ghc/lib/exts/MutableArray.lhs @@ -327,7 +327,7 @@ writeInt16Array (MutableByteArray ixs arr#) n i = ST $ \ s# -> (# 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# -> diff --git a/ghc/lib/posix/Posix.lhs b/ghc/lib/posix/Posix.lhs index 93f70a226a1b..b758e07367e9 100644 --- a/ghc/lib/posix/Posix.lhs +++ b/ghc/lib/posix/Posix.lhs @@ -84,7 +84,7 @@ runProcess path args env dir stdin stdout stderr = do pid <- forkProcess case pid of Nothing -> doTheBusiness - Just x -> return () + Just _ -> return () where doTheBusiness :: IO () doTheBusiness = do diff --git a/ghc/lib/posix/PosixIO.lhs b/ghc/lib/posix/PosixIO.lhs index 8a0713be489c..4baf00764832 100644 --- a/ghc/lib/posix/PosixIO.lhs +++ b/ghc/lib/posix/PosixIO.lhs @@ -128,8 +128,8 @@ fdToHandle fd@(FD# fd#) = 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 diff --git a/ghc/lib/posix/PosixProcEnv.lhs b/ghc/lib/posix/PosixProcEnv.lhs index 7d33f0ea8497..bd0394adf29c 100644 --- a/ghc/lib/posix/PosixProcEnv.lhs +++ b/ghc/lib/posix/PosixProcEnv.lhs @@ -245,10 +245,10 @@ getTerminalName fd = do 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 diff --git a/ghc/lib/posix/PosixProcPrim.lhs b/ghc/lib/posix/PosixProcPrim.lhs index 7e93a2111bad..ffe72145f29f 100644 --- a/ghc/lib/posix/PosixProcPrim.lhs +++ b/ghc/lib/posix/PosixProcPrim.lhs @@ -178,7 +178,7 @@ getGroupProcessStatus block stopped pgid = do 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 diff --git a/ghc/lib/std/Ix.lhs b/ghc/lib/std/Ix.lhs index 9b25f62970df..1ed8bc256709 100644 --- a/ghc/lib/std/Ix.lhs +++ b/ghc/lib/std/Ix.lhs @@ -80,7 +80,7 @@ instance Ix Char where 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" @@ -95,7 +95,7 @@ instance Ix Int where 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" @@ -109,7 +109,7 @@ instance Ix Integer where 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" @@ -249,13 +249,13 @@ in the range for an @Ix@ pair. {-# 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 diff --git a/ghc/lib/std/List.lhs b/ghc/lib/std/List.lhs index 680c5c39747e..abdde601ff1a 100644 --- a/ghc/lib/std/List.lhs +++ b/ghc/lib/std/List.lhs @@ -253,9 +253,11 @@ transpose ((x:xs) : xss) = (x : [h | (h:t) <- xss]) : transpose (xs : [ t | (h:t -- 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 diff --git a/ghc/lib/std/Monad.lhs b/ghc/lib/std/Monad.lhs index 8f631159bf5d..f95e1cb91bec 100644 --- a/ghc/lib/std/Monad.lhs +++ b/ghc/lib/std/Monad.lhs @@ -83,12 +83,15 @@ sequence [] = return [] 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 () @@ -108,6 +111,7 @@ filterM predM (x:xs) = do -- 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] #-} diff --git a/ghc/lib/std/PrelArr.lhs b/ghc/lib/std/PrelArr.lhs index c0da09cf8db6..8165fac1ff80 100644 --- a/ghc/lib/std/PrelArr.lhs +++ b/ghc/lib/std/PrelArr.lhs @@ -145,8 +145,10 @@ arrEleBottom = error "(Array.!): undefined array element" ----------------------------------------------------------------------- --- 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: @@ -157,23 +159,25 @@ old_array // ivs ) 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: @@ -183,11 +187,12 @@ accum f old_array ivs 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} diff --git a/ghc/lib/std/PrelBase.lhs b/ghc/lib/std/PrelBase.lhs index e3d4d6f2284f..b48a3e619b6c 100644 --- a/ghc/lib/std/PrelBase.lhs +++ b/ghc/lib/std/PrelBase.lhs @@ -55,10 +55,10 @@ class (Eq a) => Ord a where -- 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 @@ -99,6 +99,7 @@ data [] a = [] | a : [a] -- do explicitly: deriving (Eq, Ord) -- 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 @@ -106,6 +107,7 @@ instance (Eq a) => Eq [a] where 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 } diff --git a/ghc/lib/std/PrelEnum.lhs b/ghc/lib/std/PrelEnum.lhs index 05eb48aba73d..8d88920c69df 100644 --- a/ghc/lib/std/PrelEnum.lhs +++ b/ghc/lib/std/PrelEnum.lhs @@ -72,8 +72,8 @@ instance Bounded () where 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" @@ -153,7 +153,7 @@ instance Enum Ordering where 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 @@ -176,10 +176,10 @@ instance Bounded Char where 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") diff --git a/ghc/lib/std/PrelHandle.lhs b/ghc/lib/std/PrelHandle.lhs index 27c214330fa0..337184f2e26e 100644 --- a/ghc/lib/std/PrelHandle.lhs +++ b/ghc/lib/std/PrelHandle.lhs @@ -1123,10 +1123,6 @@ wantRWHandle fun handle act = 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 = diff --git a/ghc/lib/std/PrelList.lhs b/ghc/lib/std/PrelList.lhs index 6983e85fd15a..1d32fd72b945 100644 --- a/ghc/lib/std/PrelList.lhs +++ b/ghc/lib/std/PrelList.lhs @@ -181,7 +181,7 @@ scanr1 _ [] = errorEmptyList "scanr1" -- 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) @@ -195,7 +195,7 @@ iterateList f x = x : iterateList 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 @@ -456,15 +456,15 @@ xs !! (I# n) | n <# 0# = error "Prelude.(!!): negative index\n" %********************************************************* \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 @@ -526,7 +526,7 @@ zipWithFB c f x y r = (x `f` y) `c` r 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 @@ -541,9 +541,11 @@ zipWith3 _ _ _ _ = [] -- 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} diff --git a/ghc/lib/std/PrelNum.lhs b/ghc/lib/std/PrelNum.lhs index b6fc0d1cfeaf..a946e1b3f994 100644 --- a/ghc/lib/std/PrelNum.lhs +++ b/ghc/lib/std/PrelNum.lhs @@ -247,15 +247,15 @@ instance Ord Integer where } 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 @@ -263,8 +263,8 @@ instance Num Integer where = 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 @@ -272,12 +272,12 @@ instance Num Integer where = 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 @@ -310,8 +310,8 @@ instance Integral Integer where -- 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 #) @@ -359,8 +359,8 @@ instance Enum Integer where {-# 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) diff --git a/ghc/lib/std/PrelShow.lhs b/ghc/lib/std/PrelShow.lhs index 59b768b5e65b..b9ee6233c8bc 100644 --- a/ghc/lib/std/PrelShow.lhs +++ b/ghc/lib/std/PrelShow.lhs @@ -99,13 +99,13 @@ instance Show Int where 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} diff --git a/ghc/lib/std/Random.lhs b/ghc/lib/std/Random.lhs index e6135c28d9e5..998ed0f08fbd 100644 --- a/ghc/lib/std/Random.lhs +++ b/ghc/lib/std/Random.lhs @@ -63,7 +63,7 @@ instance Show StdGen where 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. @@ -220,7 +220,7 @@ stdNext (StdGen s1 s2) = (z', StdGen s1'' s2'') 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} -- GitLab