[commit: ghc] master: Improve wrapTicks performance with lots of redundant source notes (2912231)

git at git.haskell.org git at git.haskell.org
Sat Feb 4 23:08:36 UTC 2017


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/29122312cc7b8f9890eb53f92d76ecdd8ded24ee/ghc

>---------------------------------------------------------------

commit 29122312cc7b8f9890eb53f92d76ecdd8ded24ee
Author: Peter Wortmann <Peter.Wortmann at googlemail.com>
Date:   Sat Feb 4 15:14:31 2017 -0500

    Improve wrapTicks performance with lots of redundant source notes
    
    The old version had O(n^3) performance for n non-overlapping source
    notes and let floats each, which is exactly what happens with -g if we
    compile a list literal of length n.
    
    The idea here is simply to establish early which source notes will
    actually survive (e.g. use a left fold). The new code should be O(n) for
    list literals.
    
    Reviewers: austin, dfeuer, bgamari
    
    Reviewed By: bgamari
    
    Subscribers: thomie
    
    Differential Revision: https://phabricator.haskell.org/D3037
    
    GHC Trac Issues: #11095


>---------------------------------------------------------------

29122312cc7b8f9890eb53f92d76ecdd8ded24ee
 compiler/coreSyn/CorePrep.hs | 19 ++++++++++++++-----
 1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/compiler/coreSyn/CorePrep.hs b/compiler/coreSyn/CorePrep.hs
index 74de5af..ab64449 100644
--- a/compiler/coreSyn/CorePrep.hs
+++ b/compiler/coreSyn/CorePrep.hs
@@ -1565,11 +1565,20 @@ newVar ty
 
 -- | Like wrapFloats, but only wraps tick floats
 wrapTicks :: Floats -> CoreExpr -> (Floats, CoreExpr)
-wrapTicks (Floats flag floats0) expr = (Floats flag floats1, expr')
-  where (floats1, expr') = foldrOL go (nilOL, expr) floats0
-        go (FloatTick t) (fs, e) = ASSERT(tickishPlace t == PlaceNonLam)
-                                   (mapOL (wrap t) fs, mkTick t e)
-        go other         (fs, e) = (other `consOL` fs, e)
+wrapTicks (Floats flag floats0) expr =
+    (Floats flag (toOL $ reverse floats1), foldr mkTick expr (reverse ticks1))
+  where (floats1, ticks1) = foldlOL go ([], []) $ floats0
+        -- Deeply nested constructors will produce long lists of
+        -- redundant source note floats here. We need to eliminate
+        -- those early, as relying on mkTick to spot it after the fact
+        -- can yield O(n^3) complexity [#11095]
+        go (floats, ticks) (FloatTick t)
+          = ASSERT(tickishPlace t == PlaceNonLam)
+            (floats, if any (flip tickishContains t) ticks
+                     then ticks else t:ticks)
+        go (floats, ticks) f
+          = (foldr wrap f (reverse ticks):floats, ticks)
+
         wrap t (FloatLet bind)    = FloatLet (wrapBind t bind)
         wrap t (FloatCase b r ok) = FloatCase b (mkTick t r) ok
         wrap _ other              = pprPanic "wrapTicks: unexpected float!"



More information about the ghc-commits mailing list