Skip to content

Make small INLINE functions behave properly

Here's a desirable patch:

modified   compiler/coreSyn/CoreUnfold.hs
@@ -441,10 +441,10 @@ inlineBoringOk e
     go :: Int -> CoreExpr -> Bool
     go credit (Lam x e) | isId x           = go (credit+1) e
                         | otherwise        = go credit e
-    go credit (App f (Type {}))            = go credit f
-    go credit (App f a) | credit > 0
+    go credit (App f a) | isTyCoArg a      = go credit f
+                        | credit > 0
                         , exprIsTrivial a  = go (credit-1) f
-    go credit (Tick _ e)                 = go credit e -- dubious
+    go credit (Tick _ e)                   = go credit e -- dubious
     go credit (Cast e _)                   = go credit e
     go _      (Var {})                     = boringCxtOk
     go _      _                            = boringCxtNotOk
f x = g <refl> x
{-# INLINE g #-}   

Currently we check for a type arg rather than isTyCoArg. This in turn makes INLINE things look bigger than they should be, and stops them being inlined into boring contexts when they perfectly well could be. E.g.

f x = g <refl> x
{-# INLINE g #-} 

....(map (f x) xs)....

The context is boring, so don't inline unconditionally. But f's rhs is no bigger than its call, provided you realise that the coercion argument is ultimately cost-free.

This happens in practice for $WHRefl.

It's not a big deal: at most it means we have an extra function call overhead. But it's untidy, and actually worse than what happens without an INLINE pragma.

So, worth fixing. Perhaps a nofib-perf-test to check I haven't messed up.

Split out of !1381 (closed)

Edited by Ryan Scott
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information