Inlining of `any @[]` vs `elem @[]`
Simon Peyton Jones
simonpj at microsoft.com
Thu Mar 11 17:54:44 UTC 2021
Gergo
With HEAD, and -O, I get the exact same (good code) for these two functions:
f x = any (x ==) [1, 5, 7::Int]
g x = elem x [2, 6, 9 :: Int]
namely
f = \ (x_aga :: Int) ->
case x_aga of { GHC.Types.I# x1_a13b ->
case x1_a13b of {
__DEFAULT -> GHC.Types.False;
1# -> GHC.Types.True;
5# -> GHC.Types.True;
7# -> GHC.Types.True
}
}
g = \ (x_aQu :: Int) ->
case x_aQu of { GHC.Types.I# x1_a13b ->
case x1_a13b of {
__DEFAULT -> GHC.Types.False;
2# -> GHC.Types.True;
6# -> GHC.Types.True;
9# -> GHC.Types.True
}
}
Maybe this is fixed? If you think not, maybe open a ticket?
Simon
| -----Original Message-----
| From: ghc-devs <ghc-devs-bounces at haskell.org> On Behalf Of ÉRDI Gergo
| Sent: 07 March 2021 02:59
| To: GHC Devs <ghc-devs at haskell.org>
| Subject: Inlining of `any @[]` vs `elem @[]`
|
| Hi,
|
| The inlining behaviour of `any @[]` and `elem @[]` differs in a way
| that I am not sure is intentional, and it is affecting Clash (see
| https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgith
| ub.com%2Fclash-lang%2Fclash-
| compiler%2Fissues%2F1691&data=04%7C01%7Csimonpj%40microsoft.com%7C
| e37a9761e8814eada5f208d8e115026d%7C72f988bf86f141af91ab2d7cd011db47%7C
| 1%7C0%7C637506827802688772%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDA
| iLCJQIjoiV2luMzIiLCJBTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=Kik8v
| KuwNobr9kiQOcIHuKTn%2BbEmQ7oY8tqP9tFjs6M%3D&reserved=0). I would
| think that if it is a good idea to inline `any` then inlining `elem`
| would be just as good an idea, or vice versa.
|
| However, `any` is defined polymorphically over `Foldable`, via
| `foldMap` using `foldr`, with all steps between (and `foldr @[]`!)
| marked as `INLINE`. The result is that if you use `any (x ==) [1, 5,
| 7]` you get the following beautiful Core:
|
| ```
| topEntity
| = \ (x_agAF :: Int) ->
| case x_agAF of { GHC.Types.I# y_ahao ->
| case y_ahao of {
| __DEFAULT -> GHC.Types.False;
| 1# -> GHC.Types.True;
| 5# -> GHC.Types.True;
| 7# -> GHC.Types.True
| }
| }
| ```
|
| As the kids these days would say: *chef's kiss*.
|
|
| `elem`, on the other hand, is a typeclass method of `Foldable`, with a
| default implementation in terms of `any`, but overridden for lists
| with the following implementation:
|
| ```
| GHC.List.elem :: (Eq a) => a -> [a] -> Bool
| GHC.List.elem _ [] = False
| GHC.List.elem x (y:ys) = x==y || GHC.List.elem x ys
| {-# NOINLINE [1] elem #-}
| {-# RULES
| "elem/build" forall x (g :: forall b . Eq a => (a -> b -> b) -> b -
| > b)
| . elem x (build g) = g (\ y r -> (x == y) || r) False
| #-}
| ```
|
| This is marked as non-inlineable until phase 1 (so that `elem/build`
| has a chance of firing), but it seems that when build fusion doesn't
| apply (since `[1, 5, 7]` is, of course, not built via `build`), no
| inlining happens AT ALL, even in later phases, so we end up with this:
|
| ```
| topEntity
| = \ (x_agAF :: Int) ->
| GHC.List.elem
| @ Int
| GHC.Classes.$fEqInt
| x_agAF
| (GHC.Types.:
| @ Int
| (GHC.Types.I# 1#)
| (GHC.Types.:
| @ Int
| (GHC.Types.I# 5#)
| (GHC.Types.: @ Int (GHC.Types.I# 7#) (GHC.Types.[] @
| Int)))) ```
|
| So not only does it trip up Clash, it would also result in less
| efficient code in software when using "normal" GHC.
|
| Is this all intentional? Wouldn't it make more sense to mark
| `GHC.List.elem` as `INLINE [1]` instead of `NOINLINE [1]`, so that any
| calls remaining after build fusion would be inlined?
|
| Thanks,
| Gergo
| _______________________________________________
| ghc-devs mailing list
| ghc-devs at haskell.org
| https://nam06.safelinks.protection.outlook.com/?url=http%3A%2F%2Fmail.
| haskell.org%2Fcgi-bin%2Fmailman%2Flistinfo%2Fghc-
| devs&data=04%7C01%7Csimonpj%40microsoft.com%7Ce37a9761e8814eada5f2
| 08d8e115026d%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637506827802
| 688772%7CUnknown%7CTWFpbGZsb3d8eyJWIjoiMC4wLjAwMDAiLCJQIjoiV2luMzIiLCJ
| BTiI6Ik1haWwiLCJXVCI6Mn0%3D%7C1000&sdata=yMXu0XJQU2GmlDTH9ZaHXhl33
| ZRBjHMe41rr8lKVxkk%3D&reserved=0
More information about the ghc-devs
mailing list