X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=ghc%2Fcompiler%2FsimplCore%2FFloatIn.lhs;h=0e8edb5930b314921725f7fed3b80256061863d0;hb=28a464a75e14cece5db40f2765a29348273ff2d2;hp=f974d12f1b76aa9af13f57a6d6054d4c9f986c7e;hpb=f23ba2b294429ccbdeb80f0344ec08f6abf61bb7;p=ghc-hetmet.git diff --git a/ghc/compiler/simplCore/FloatIn.lhs b/ghc/compiler/simplCore/FloatIn.lhs index f974d12..0e8edb5 100644 --- a/ghc/compiler/simplCore/FloatIn.lhs +++ b/ghc/compiler/simplCore/FloatIn.lhs @@ -16,16 +16,16 @@ module FloatIn ( floatInwards ) where #include "HsVersions.h" -import CmdLineOpts ( DynFlags, DynFlag(..), dopt ) +import DynFlags ( DynFlags, DynFlag(..) ) import CoreSyn -import CoreUtils ( exprIsValue, exprIsDupable ) +import CoreUtils ( exprIsHNF, exprIsDupable ) import CoreLint ( showPass, endPass ) import CoreFVs ( CoreExprWithFVs, freeVars, freeVarsOf ) -import Id ( isOneShotLambda ) -import Var ( Id, idType, isTyVar ) +import Id ( isOneShotBndr ) +import Var ( Id, idType ) import Type ( isUnLiftedType ) import VarSet -import Util ( zipEqual, zipWithEqual ) +import Util ( zipEqual, zipWithEqual, count ) import Outputable \end{code} @@ -39,10 +39,8 @@ floatInwards dflags binds = do { showPass dflags "Float inwards"; let { binds' = map fi_top_bind binds }; - endPass dflags "Float inwards" - (dopt Opt_D_verbose_core2core dflags) + endPass dflags "Float inwards" Opt_D_verbose_core2core binds' {- no specific flag for dumping float-in -} - binds' } where @@ -181,16 +179,23 @@ So we treat lambda in groups, using the following rule: Otherwise drop all the bindings outside the group. \begin{code} -fiExpr to_drop (_, AnnLam b body) - = case collect [b] body of - (bndrs, real_body) - | all is_ok bndrs -> mkLams bndrs (fiExpr to_drop real_body) - | otherwise -> mkCoLets' to_drop (mkLams bndrs (fiExpr [] real_body)) - where - collect bs (_, AnnLam b body) = collect (b:bs) body - collect bs body = (reverse bs, body) + -- Hack alert! We only float in through one-shot lambdas, + -- not (as you might guess) through big lambdas. + -- Reason: we float *out* past big lambdas (see the test in the Lam + -- case of FloatOut.floatExpr) and we don't want to float straight + -- back in again. + -- + -- It *is* important to float into one-shot lambdas, however; + -- see the remarks with noFloatIntoRhs. +fiExpr to_drop lam@(_, AnnLam _ _) + | all is_one_shot bndrs -- Float in + = mkLams bndrs (fiExpr to_drop body) + + | otherwise -- Dump it all here + = mkCoLets' to_drop (mkLams bndrs (fiExpr [] body)) - is_ok bndr = isTyVar bndr || isOneShotLambda bndr + where + (bndrs, body) = collectAnnBndrs lam \end{code} We don't float lets inwards past an SCC. @@ -215,6 +220,9 @@ fiExpr to_drop (_, AnnNote InlineMe expr) fiExpr to_drop (_, AnnNote note@(Coerce _ _) expr) = -- Just float in past coercion Note note (fiExpr to_drop expr) + +fiExpr to_drop (_, AnnNote note@(CoreNote _) expr) + = Note note (fiExpr to_drop expr) \end{code} For @Lets@, the possible ``drop points'' for the \tr{to_drop} @@ -315,10 +323,10 @@ bindings are: (a)~inside the scrutinee, (b)~inside one of the alternatives/default [default FVs always {\em first}!]. \begin{code} -fiExpr to_drop (_, AnnCase scrut case_bndr alts) +fiExpr to_drop (_, AnnCase scrut case_bndr ty alts) = mkCoLets' drop_here1 $ mkCoLets' drop_here2 $ - Case (fiExpr scrut_drops scrut) case_bndr + Case (fiExpr scrut_drops scrut) case_bndr ty (zipWith fi_alt alts_drops_s alts) where -- Float into the scrut and alts-considered-together just like App @@ -337,7 +345,7 @@ fiExpr to_drop (_, AnnCase scrut case_bndr alts) fi_alt to_drop (con, args, rhs) = (con, args, fiExpr to_drop rhs) noFloatIntoRhs (AnnNote InlineMe _) = True -noFloatIntoRhs (AnnLam b _) = not (isId b && isOneShotLambda b) +noFloatIntoRhs (AnnLam b _) = not (is_one_shot b) -- IMPORTANT: don't say 'True' for a RHS with a one-shot lambda at the top. -- This makes a big difference for things like -- f x# = let x = I# x# @@ -347,7 +355,9 @@ noFloatIntoRhs (AnnLam b _) = not (isId b && isOneShotLambda b) -- boxing constructor into it, else we box it every time which is very bad -- news indeed. -noFloatIntoRhs rhs = exprIsValue (deAnnotate' rhs) -- We'd just float rigt back out again... +noFloatIntoRhs rhs = exprIsHNF (deAnnotate' rhs) -- We'd just float right back out again... + +is_one_shot b = isId b && isOneShotBndr b \end{code} @@ -422,7 +432,7 @@ sepBindsByDropPoint is_case drop_pts floaters -- E -> ...not mentioning x... n_alts = length used_in_flags - n_used_alts = length [() | True <- used_in_flags] + n_used_alts = count id used_in_flags -- returns number of Trues in list. can_push = n_used_alts == 1 -- Used in just one branch || (is_case && -- We are looking at case alternatives