Make seq# evaluatedness look through casts
authorDavid Feuer <david.feuer@gmail.com>
Mon, 11 Jun 2018 14:32:23 +0000 (10:32 -0400)
committerDavid Feuer <David.Feuer@gmail.com>
Mon, 11 Jun 2018 14:33:40 +0000 (10:33 -0400)
In d964b05, I forgot to look through casts to find the `seq#`
identifier. Fix that.

Reviewers: bgamari

Reviewed By: bgamari

Subscribers: rwbarton, thomie, carter

Differential Revision: https://phabricator.haskell.org/D4804

compiler/coreSyn/CoreSyn.hs
testsuite/tests/perf/should_run/T15226a.hs [new file with mode: 0644]
testsuite/tests/perf/should_run/all.T

index 4dd70b0..50e40d1 100644 (file)
@@ -2046,10 +2046,11 @@ collectArgs expr
     go e         as = (e, as)
 
 -- | Attempt to remove the last N arguments of a function call.
--- Strip off any ticks encountered along the way and any ticks
+-- Strip off any ticks or coercions encountered along the way and any
 -- at the end.
 stripNArgs :: Word -> Expr a -> Maybe (Expr a)
 stripNArgs !n (Tick _ e) = stripNArgs n e
+stripNArgs n (Cast f _) = stripNArgs n f
 stripNArgs 0 e = Just e
 stripNArgs n (App f _) = stripNArgs (n - 1) f
 stripNArgs _ _ = Nothing
diff --git a/testsuite/tests/perf/should_run/T15226a.hs b/testsuite/tests/perf/should_run/T15226a.hs
new file mode 100644 (file)
index 0000000..6e9a1db
--- /dev/null
@@ -0,0 +1,33 @@
+-- T15226
+import Control.Exception (evaluate)
+
+-- Just in case Prelude.repeat changes for some reason.
+import Prelude hiding (repeat)
+import Data.Coerce
+
+-- We want to be sure that the compiler *doesn't* know that
+-- all the elements of the list are in WHNF, because if it
+-- does, PrelRules may erase the seq#'s altogether.
+repeat :: a -> [a]
+repeat a = res
+  where res = a : res
+{-# NOINLINE repeat #-}  -- Belt *and* suspenders
+
+newtype Foo = Foo Int
+
+silly :: [Int] -> IO ()
+silly = foldr go (pure ())
+  where
+    go x r = do
+      x' <- (coerce (evaluate :: Foo -> IO Foo) :: Int -> IO Int) x
+      evaluate (x' + 3)  -- GHC should know that x' has been evaluated,
+                         -- so this calculation will be erased entirely.
+                         -- Otherwise, we'll create a thunk to pass to
+                         -- evaluate.
+      r
+
+main :: IO ()
+-- 10,000,000 repetitions take only a twentieth of a second,
+-- but allocations go up dramatically if the result is not
+-- known evaluated.
+main = silly $ take 10000000 $ repeat 1
index b248dd5..0e7996e 100644 (file)
@@ -584,3 +584,12 @@ test('T15226',
      only_ways(['normal'])],
     compile_and_run,
     ['-O'])
+
+test('T15226a',
+    [stats_num_field('bytes allocated',
+                    [ (wordsize(64), 41040, 5) ]),
+                    # 2018-06-06   41040  Look through casts for seq#
+                    # initial  400041040
+     only_ways(['normal'])],
+    compile_and_run,
+    ['-O'])