X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fstranal%2FWorkWrap.lhs;h=ac10b1b7737bd84347e76282d05e16b1df56fd63;hp=a8f110c96c1b7081596ebe85ddf65c3493f8154f;hb=0af06ed99ed56341adfdda4a92a0a36678780109;hpb=51367fba96fd863ce7d3e2571bd22366b47b900a diff --git a/compiler/stranal/WorkWrap.lhs b/compiler/stranal/WorkWrap.lhs index a8f110c..ac10b1b 100644 --- a/compiler/stranal/WorkWrap.lhs +++ b/compiler/stranal/WorkWrap.lhs @@ -100,6 +100,7 @@ matching by looking for strict arguments of the correct type. wwExpr :: CoreExpr -> UniqSM CoreExpr wwExpr e@(Type {}) = return e +wwExpr e@(Coercion {}) = return e wwExpr e@(Lit {}) = return e wwExpr e@(Var {}) = return e @@ -141,9 +142,8 @@ the business. The only reason this is monadised is for the unique supply. -Note [Don't w/w inline things (a)] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - +Note [Don't w/w INLINE things] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ It's very important to refrain from w/w-ing an INLINE function (ie one with an InlineRule) because the wrapper will then overwrite the InlineRule unfolding. @@ -160,19 +160,6 @@ Notice that we refrain from w/w'ing an INLINE function even if it is in a recursive group. It might not be the loop breaker. (We could test for loop-breaker-hood, but I'm not sure that ever matters.) -Note [Don't w/w inline things (b)] -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -In general, we refrain from w/w-ing *small* functions, because they'll -inline anyway. But we must take care: it may look small now, but get -to be big later after other inling has happened. So we take the -precaution of adding an INLINE pragma to any such functions. - -I made this change when I observed a big function at the end of -compilation with a useful strictness signature but no w-w. When -I measured it on nofib, it didn't make much difference; just a few -percent improved allocation on one benchmark (bspt/Euclid.space). -But nothing got worse. - Note [Don't w/w INLINABLE things] ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ If we have @@ -187,6 +174,32 @@ an INLINABLE pragma could make a program a bit less efficient, because you lose the worker/wrapper stuff. But I don't see a way to avoid that. +Note [Don't w/w inline small non-loop-breaker things] +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +In general, we refrain from w/w-ing *small* functions, which are not +loop breakers, because they'll inline anyway. But we must take care: +it may look small now, but get to be big later after other inlining +has happened. So we take the precaution of adding an INLINE pragma to +any such functions. + +I made this change when I observed a big function at the end of +compilation with a useful strictness signature but no w-w. (It was +small during demand analysis, we refrained from w/w, and then got big +when something was inlined in its rhs.) When I measured it on nofib, +it didn't make much difference; just a few percent improved allocation +on one benchmark (bspt/Euclid.space). But nothing got worse. + +There is an infelicity though. We may get something like + f = g val +==> + g x = case gw x of r -> I# r + + f {- InlineStable, Template = g val -} + f = case gw x of r -> I# r + +The code for f duplicates that for g, without any real benefit. It +won't really be executed, because calls to f will go via the inlining. + Note [Wrapper activation] ~~~~~~~~~~~~~~~~~~~~~~~~~ When should the wrapper inlining be active? It must not be active @@ -273,21 +286,22 @@ tryWW is_rec fn_id rhs --------------------- checkSize :: Id -> CoreExpr -> UniqSM [(Id,CoreExpr)] -> UniqSM [(Id,CoreExpr)] - -- See Note [Don't w/w inline things (a) and (b)] - -- and Note [Don't w/w INLINABLE things] checkSize fn_id rhs thing_inside - | isStableUnfolding unfolding -- For DFuns and INLINE things, leave their - = return [ (fn_id, rhs) ] -- unfolding unchanged; but still attach - -- strictness info to the Id + | isStableUnfolding (realIdUnfolding fn_id) + = return [ (fn_id, rhs) ] + -- See Note [Don't w/w INLINABLE things] + -- and Note [Don't w/w INLINABLABLE things] + -- NB: use realIdUnfolding because we want to see the unfolding + -- even if it's a loop breaker! - | certainlyWillInline unfolding + | certainlyWillInline (idUnfolding fn_id) = return [ (fn_id `setIdUnfolding` inline_rule, rhs) ] - -- Note [Don't w/w inline things (b)] + -- Note [Don't w/w inline small non-loop-breaker things] + -- NB: use idUnfolding because we don't want to apply + -- this criterion to a loop breaker! | otherwise = thing_inside where - unfolding = realIdUnfolding fn_id -- We want to see the unfolding - -- for loop breakers! inline_rule = mkInlineUnfolding Nothing rhs --------------------- @@ -412,6 +426,11 @@ then the splitting will go deeper too. -- in case x of -- I# y -> let x = I# y in x } -- See comments above. Is it not beautifully short? +-- Moreover, it works just as well when there are +-- several binders, and if the binders are lifted +-- E.g. x = e +-- --> x = let x = e in +-- case x of (a,b) -> let x = (a,b) in x splitThunk :: Var -> Expr Var -> UniqSM [(Var, Expr Var)] splitThunk fn_id rhs = do