Skip to content

Instantly share code, notes, and snippets.

@danidiaz
Last active October 29, 2023 08:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save danidiaz/c6590ce5236578f58b696c0c4f60110c to your computer and use it in GitHub Desktop.
Save danidiaz/c6590ce5236578f58b696c0c4f60110c to your computer and use it in GitHub Desktop.
Example of how the case-of-known-constructor can remove the use of a record
-- https://www.reddit.com/r/haskell/comments/170f6qa/comment/k6spn9n/
-- Compare the core of
-- ghc -O0 -c Main.hs -ddump-to-file -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes -fforce-recomp
-- with the core of
-- ghc -O2 -c Main.hs -ddump-to-file -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes -fforce-recomp
-- search for "foofun".
module Main (main) where
data Foo = Foo
{ aaa :: Int,
bbb :: Int,
ccc :: Int,
ddd :: Int
}
-- The function doesn't do anything meaningful, it's only for
-- testing that the Foo is optimized away.
foofun :: Foo -> Int -> Int
foofun Foo {aaa, bbb, ccc, ddd} 0 = aaa + bbb + ccc + ddd
foofun Foo {aaa, bbb, ccc, ddd} n =
foofun
Foo
{ aaa = aaa + 1,
bbb = bbb + 1,
ccc = ccc + 1,
ddd = ddd + 1
}
(n - 1)
main :: IO ()
main = print (foofun Foo {aaa = 1, bbb = 1, ccc = 1, ddd = 1} 7)
{-# LANGUAGE OverloadedRecordDot #-}
-- https://www.reddit.com/r/haskell/comments/170f6qa/comment/k6spn9n/
-- Compare the core of
-- ghc -O0 -c Main.hs -ddump-to-file -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes -fforce-recomp
-- with the core of
-- ghc -O2 -c Main.hs -ddump-to-file -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes -fforce-recomp
-- search for "foofun".
module Main (main) where
data Foo = Foo
{ aaa :: Int,
bbb :: Int,
ccc :: Int,
ddd :: Int
}
-- The function doesn't do anything meaningful, it's only for
-- testing that the Foo is optimized away.
foofun :: Foo -> Int -> Int
foofun foo 0 = foo.aaa + foo.bbb + foo.ccc + foo.ddd
foofun foo n =
foofun
Foo
{ aaa = foo.aaa + 1,
bbb = foo.bbb + 1,
ccc = foo.ccc + 1,
ddd = foo.ddd + 1
}
(n - 1)
main :: IO ()
main = print (foofun Foo {aaa = 1, bbb = 1, ccc = 1, ddd = 1} 7)
-- https://www.reddit.com/r/haskell/comments/170f6qa/comment/k6spn9n/
-- Compare the core of
-- ghc -O0 -c Main.hs -ddump-to-file -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes -fforce-recomp
-- with the core of
-- ghc -O2 -c Main.hs -ddump-to-file -ddump-simpl -dsuppress-idinfo -dsuppress-coercions -dsuppress-type-applications -dsuppress-uniques -dsuppress-module-prefixes -fforce-recomp
-- search for "foofun".
module Main (main, foofun) where
data Foo = Foo
{ aaa :: Int,
bbb :: Int,
ccc :: Int,
ddd :: Int
}
-- The function doesn't do anything meaningful, it's only for
-- testing that the Foo is optimized away.
foofun :: Foo -> Int -> (Int, Int)
foofun Foo {aaa, bbb, ccc, ddd} 0 = do
let !x = aaa + bbb
let !y = ccc + ddd
-- Removing the stricness bangs result in way worse core.
-- The worker won't use unboxed Ints in the result tuple!
-- See https://www.youtube.com/watch?v=wC9cpQk7WWA
-- and https://ghc.gitlab.haskell.org/ghc/doc/users_guide/using-optimisation.html#ghc-flag--fstrictness
-- let x = aaa + bbb
-- let y = ccc + ddd
(x, y)
foofun Foo {aaa, bbb, ccc, ddd} n =
foofun
Foo
{ aaa = aaa + 1,
bbb = bbb + 1,
ccc = ccc + 1,
ddd = ddd + 1
}
(n - 1)
main :: IO ()
main = print (foofun Foo {aaa = 1, bbb = 1, ccc = 1, ddd = 1} 7)
Rec {
-- RHS size: {terms: 49, types: 18, coercions: 0, joins: 0/0}
foofun :: Foo -> Int -> Int
foofun
= \ (ds :: Foo) (ds1 :: Int) ->
case ds of { Foo ds2 ds3 ds4 ds5 ->
case ds1 of wild1 { I# ds6 ->
case ds6 of {
__DEFAULT ->
foofun
(Foo
(+ $fNumInt ds2 (I# 1#))
(+ $fNumInt ds3 (I# 1#))
(+ $fNumInt ds4 (I# 1#))
(+ $fNumInt ds5 (I# 1#)))
(- $fNumInt wild1 (I# 1#));
0# -> + $fNumInt (+ $fNumInt (+ $fNumInt ds2 ds3) ds4) ds5
}
}
}
end Rec }
Rec {
-- RHS size: {terms: 32, types: 6, coercions: 0, joins: 0/0}
$wfoofun :: Int# -> Int# -> Int# -> Int# -> Int# -> Int#
$wfoofun
= \ (ww :: Int#)
(ww1 :: Int#)
(ww2 :: Int#)
(ww3 :: Int#)
(ww4 :: Int#) ->
case ww4 of ds {
__DEFAULT ->
$wfoofun (+# ww 1#) (+# ww1 1#) (+# ww2 1#) (+# ww3 1#) (-# ds 1#);
0# -> +# (+# (+# ww ww1) ww2) ww3
}
end Rec }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment