diff options
-rw-r--r-- | compiler/simplCore/SetLevels.lhs | 3 | ||||
-rw-r--r-- | compiler/specialise/Specialise.lhs | 35 | ||||
-rw-r--r-- | compiler/stranal/WorkWrap.lhs | 6 |
3 files changed, 34 insertions, 10 deletions
diff --git a/compiler/simplCore/SetLevels.lhs b/compiler/simplCore/SetLevels.lhs index c69687b424..5f63096a29 100644 --- a/compiler/simplCore/SetLevels.lhs +++ b/compiler/simplCore/SetLevels.lhs @@ -352,6 +352,9 @@ lvlExpr env expr@(_, AnnLam {}) lvlExpr env (_, AnnLet bind body) = do { (bind', new_env) <- lvlBind env bind ; body' <- lvlExpr new_env body + -- No point in going via lvlMFE here. If the binding is alive + -- (mentioned in body), and the whole let-expression doesn't + -- float, then neither will the body ; return (Let bind' body') } lvlExpr env (_, AnnCase scrut@(scrut_fvs,_) case_bndr ty alts) diff --git a/compiler/specialise/Specialise.lhs b/compiler/specialise/Specialise.lhs index 5a2b8cd672..ee8f69315c 100644 --- a/compiler/specialise/Specialise.lhs +++ b/compiler/specialise/Specialise.lhs @@ -1496,9 +1496,9 @@ Here is what we do with the InlinePragma of the original function (a) An INLINE pragma is transferred (b) An INLINABLE pragma is *not* transferred -Why (a)? Previously the idea is that the point of INLINE was -precisely to specialise the function at its call site, and that's not -so important for the specialised copies. But *pragma-directed* +Why (a): transfer INLINE pragmas? The point of INLINE was precisely to +specialise the function at its call site, and arguably that's not so +important for the specialised copies. BUT *pragma-directed* specialisation now takes place in the typechecker/desugarer, with manually specified INLINEs. The specialisation here is automatic. It'd be very odd if a function marked INLINE was specialised (because @@ -1509,16 +1509,33 @@ programmer said INLINE! You might wonder why we specialise INLINE functions at all. After all they should be inlined, right? Two reasons: - * Even INLINE functions are sometimes not inlined, when - they aren't applied to interesting arguments. But perhaps the type - arguments alone are enough to specialise (even though the args are too - boring to trigger inlining), and it's certainly better to call the + * Even INLINE functions are sometimes not inlined, when they aren't + applied to interesting arguments. But perhaps the type arguments + alone are enough to specialise (even though the args are too boring + to trigger inlining), and it's certainly better to call the specialised version. * The RHS of an INLINE function might call another overloaded function, and we'd like to generate a specialised version of that function too. - -Why (b)? See Trac #4874 for persuasive examples. Suppose we have + This actually happens a lot. Consider + replicateM_ :: (Monad m) => Int -> m a -> m () + {-# INLINABLE replicateM_ #-} + replicateM_ d x ma = ... + The strictness analyser may transform to + replicateM_ :: (Monad m) => Int -> m a -> m () + {-# INLINE replicateM_ #-} + replicateM_ d x ma = case x of I# x' -> $wreplicateM_ d x' ma + + $wreplicateM_ :: (Monad m) => Int# -> m a -> m () + {-# INLINABLE $wreplicateM_ #-} + $wreplicateM_ = ... + Now an importing module has a specialised call to replicateM_, say + (replicateM_ dMonadIO). We certainly want to specialise $wreplicateM_! + This particular example had a huge effect on the call to replicateM_ + in nofib/shootout/n-body. + +Why (b): discard INLINEABLE pragmas? See Trac #4874 for persuasive examples. +Suppose we have {-# INLINABLE f #-} f :: Ord a => [a] -> Int f xs = letrec f' = ...f'... in f' diff --git a/compiler/stranal/WorkWrap.lhs b/compiler/stranal/WorkWrap.lhs index f845151098..f7717ed28c 100644 --- a/compiler/stranal/WorkWrap.lhs +++ b/compiler/stranal/WorkWrap.lhs @@ -232,7 +232,7 @@ strictness. Eg if we have g :: Int -> Int g x = f x x -- Provokes a specialisation for f - module Bsr where + module Bar where import Foo h :: Int -> Int @@ -246,6 +246,10 @@ more robust to give the wrapper an Activation of (ActiveAfter 0), so that it becomes active in an importing module at the same time that it appears in the first place in the defining module. +At one stage I tried making the wrapper inlining always-active, and +that had a very bad effect on nofib/imaginary/x2n1; a wrapper was +inlined before the specialisation fired. + \begin{code} tryWW :: DynFlags -> FamInstEnvs |