Fold integer-simple.git into ghc.git (re #8545)
[ghc.git] / testsuite / tests / perf / should_run / MethSharing.hs
1 module Main where
2
3 -- This test works efficiently because the full laziness
4 -- pass now floats out applications
5 -- \x -> f y (x+1)
6 -- It'll float out the (f y) if that's a redex
7
8 loop :: Double -> [Int] -> Double
9 {-# NOINLINE loop #-}
10 loop x [] = x
11 loop x (n:ns) = x `seq` loop (x ^ n) ns
12
13 main = print $ loop 1 (replicate 10000000 5)
14
15 ----------------------------------------------------
16 {- Roman's message of May 2010
17
18 I tried running nofib with -fno-method-sharing (we discussed this at some point). These are the results:
19
20 --------------------------------------------------------------------------------
21 Program Size Allocs Runtime Elapsed
22 --------------------------------------------------------------------------------
23
24 Min -0.3% -25.0% -12.5% -9.9%
25 Max +0.2% +159.1% +90.0% +84.7%
26 Geometric Mean -0.0% +2.2% +6.8% +5.1%
27
28 This is the worst program:
29
30 simple +0.2% +159.1% +65.3% +63.9%
31
32 I looked at it a bit and came up with this small example:
33
34 ----
35 loop :: Double -> [Int] -> Double
36 {-# NOINLINE loop #-}
37 loop x [] = x
38 loop x (n:ns) = x `seq` loop (x ^ n) ns
39
40 main = print $ loop 1 (replicate 10000000 5)
41 ----
42
43 This is over 2x slower with -fno-method-sharing. The culprit is, of
44 course, (^). Here is the difference:
45
46 Without -fno-method-sharing:
47
48 ----
49 ^_rVB :: GHC.Types.Double -> GHC.Types.Int -> GHC.Types.Double ^_rVB =
50 GHC.Real.^
51 @ GHC.Types.Double
52 @ GHC.Types.Int
53 GHC.Float.$fNumDouble
54 GHC.Real.$fIntegralInt
55
56 Main.loop [InlPrag=NOINLINE (sat-args=2), Occ=LoopBreaker]
57 :: GHC.Types.Double -> [GHC.Types.Int] -> GHC.Types.Double Main.loop =
58 \ (x1_aat :: GHC.Types.Double) (ds_drG :: [GHC.Types.Int]) ->
59 case ds_drG of _ {
60 [] -> x1_aat;
61 : n_aav ns_aaw ->
62 case x1_aat of x2_aau { GHC.Types.D# ipv_srQ ->
63 Main.loop (^_rVB x2_aau n_aav) ns_aaw
64 }
65 }
66 ----
67
68 With:
69
70 ----
71 Main.loop [InlPrag=NOINLINE (sat-args=2), Occ=LoopBreaker]
72 :: GHC.Types.Double -> [GHC.Types.Int] -> GHC.Types.Double Main.loop =
73 \ (x1_aat :: GHC.Types.Double) (ds_drD :: [GHC.Types.Int]) ->
74 case ds_drD of _ {
75 [] -> x1_aat;
76 : n_aav ns_aaw ->
77 case x1_aat of x2_aau { GHC.Types.D# ipv_srN ->
78 Main.loop
79 (GHC.Real.^
80 @ GHC.Types.Double
81 @ GHC.Types.Int
82 GHC.Float.$fNumDouble
83 GHC.Real.$fIntegralInt
84 x2_aau
85 n_aav)
86 ns_aaw
87 }
88 }
89 ----
90
91 This is a bit disappointing. I would have expected GHC to float out
92 the application of (^) to the two dictionaries during full laziness
93 (note that (^) has arity 2 so the application is oversaturated). Why
94 doesn't that happen? SetLevels (if this is the right place to look)
95 has this:
96
97 -}