diff options
author | Sebastian Graf <sebastian.graf@kit.edu> | 2018-09-17 21:11:09 +0200 |
---|---|---|
committer | Krzysztof Gogolewski <krz.gogolewski@gmail.com> | 2018-09-17 21:11:10 +0200 |
commit | e655aac18c5b240f27fcaf26317ad87be5ce8b96 (patch) | |
tree | e496319636b98443874749e07791028e671ddd87 /testsuite/tests/perf/should_run | |
parent | 43967c0c7d2d0110cfc5f9d64a7dab3a3dda8953 (diff) | |
download | haskell-e655aac18c5b240f27fcaf26317ad87be5ce8b96.tar.gz |
Make sure forM_ and related functions fuse cleanly
Summary:
It was revealed in #8763 that it's hard to come up with a list fusion
helper for `efdtIntFB` that doesn't duplicated occurrences of `c`,
which is crucial in guaranteeing that it is inlined.
Not inlining `c` led to spoiled join points, in turn leading to unnecessary
heap allocation. This patch tackles the problem from a different angle:
Fixing all consumers instead of the less often used producer
`efdtIntFB` by inserting an INLINE pragma in the appropriate places.
See https://ghc.haskell.org/trac/ghc/ticket/8763#comment:76 and the new
Note [List fusion and continuations in 'c'].
A quick run of NoFib revealed no regression or improvements whatsoever.
Reviewers: hvr, bgamari, simonpj
Reviewed By: simonpj
Subscribers: simonpj, rwbarton, carter
GHC Trac Issues: #8763
Differential Revision: https://phabricator.haskell.org/D5131
Diffstat (limited to 'testsuite/tests/perf/should_run')
-rw-r--r-- | testsuite/tests/perf/should_run/T8763.hs | 41 | ||||
-rw-r--r-- | testsuite/tests/perf/should_run/all.T | 7 |
2 files changed, 48 insertions, 0 deletions
diff --git a/testsuite/tests/perf/should_run/T8763.hs b/testsuite/tests/perf/should_run/T8763.hs new file mode 100644 index 0000000000..90c4436ce9 --- /dev/null +++ b/testsuite/tests/perf/should_run/T8763.hs @@ -0,0 +1,41 @@ +-- | The fusion helper for @enumFromThenTo \@Int@ had multiple +-- occurences of @c@, which made the simplifier refuse to inline it. +-- The new implementation for @efdtInt{Up,Dn}FB@ only have a single +-- occurence of @c@ which the simplifier inlines unconditionally. +module Main (main) where + +import Control.Monad (when, forM_) +import GHC.ST + +nop :: Monad m => a -> m () +nop _ = return () +{-# NOINLINE nop #-} + +-- This is the baseline, using @enumFromTo@ which already had only a +-- single occurence of @c@. +f :: Int -> ST s () +f n = + do + forM_ [2..n] $ \p -> do + let isPrime = p == (p - 1) + when isPrime $ + forM_ [p + p, p + p + p .. n] $ \k -> do + nop k +{-# NOINLINE f #-} + +g :: Int -> ST s () +g n = + do + forM_ [2,3..n] $ \p -> do + -- This do block should be too big to get inlined multiple times. + -- Pad with @nop@s as necessary if this doesn't reproduce anymore. + let isPrime = p == (p - 1) + when isPrime $ + forM_ [p + p, p + p + p .. n] $ \k -> do + nop k +{-# NOINLINE g #-} + +main :: IO () +main = do + -- runST (f 40000000) `seq` return () + runST (g 40000000) `seq` return () diff --git a/testsuite/tests/perf/should_run/all.T b/testsuite/tests/perf/should_run/all.T index 1a85e7073d..37ce0a454f 100644 --- a/testsuite/tests/perf/should_run/all.T +++ b/testsuite/tests/perf/should_run/all.T @@ -518,6 +518,13 @@ test('T13001', compile_and_run, ['-O2']) +test('T8763', + [stats_num_field('bytes allocated', + [ (wordsize(64), 41056, 20) ]), + only_ways(['normal'])], + compile_and_run, + ['-O2']) + test('T12990', [stats_num_field('bytes allocated', [ (wordsize(64), 20040936, 5) ]), |