[commit: ghc] wip/T14152: Do some ad-hoc CSE in Exitification (154fc88)

git at git.haskell.org git at git.haskell.org
Wed Sep 6 14:19:18 UTC 2017


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

On branch  : wip/T14152
Link       : http://ghc.haskell.org/trac/ghc/changeset/154fc8861eb12656ba1bf56ea257ac4483d63d21/ghc

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

commit 154fc8861eb12656ba1bf56ea257ac4483d63d21
Author: Joachim Breitner <mail at joachim-breitner.de>
Date:   Wed Sep 6 15:17:12 2017 +0100

    Do some ad-hoc CSE in Exitification
    
    So that code like this
    
        safe :: Int -> [Int] -> [[Int]]
        safe x2 ds6
          = case ds6 of
              [] -> lvl6;
              q : l | x2     == q -> h x2 ds5
                    | x2 + 1 == q -> h x2 ds5
                    | x2 + 2 == q -> h x2 ds5
                    | x2 + 3 == q -> h x2 ds5
                    | otherwise   -> safe (x+10) l
    
    only gets one exit join point, instead of 4 identically.
    
    (There is currently no CSE for join points, and even if there were, it is cheap
    to do it here.)


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

154fc8861eb12656ba1bf56ea257ac4483d63d21
 compiler/simplCore/Exitify.hs | 37 +++++++++++++++++++++++++------------
 1 file changed, 25 insertions(+), 12 deletions(-)

diff --git a/compiler/simplCore/Exitify.hs b/compiler/simplCore/Exitify.hs
index 916ae73..c1b64b1 100644
--- a/compiler/simplCore/Exitify.hs
+++ b/compiler/simplCore/Exitify.hs
@@ -11,6 +11,7 @@ import VarSet
 import VarEnv
 import CoreFVs
 import FastString
+import TrieMap
 import Type
 
 import Data.Bifunctor
@@ -71,13 +72,14 @@ exitify in_scope pairs =
     -- Which are the recursive calls?
     recursive_calls = mkVarSet $ map fst pairs
 
-    (pairs',exits) = (`runState` []) $ do
+    (pairs',st) = (`runState` ExitifyState [] emptyTM) $ do
         forM ann_pairs $ \(x,rhs) -> do
             -- go past the lambdas of the join point
             let (args, body) = collectNAnnBndrs (idJoinArity x) rhs
             body' <- go args body
             let rhs' = mkLams args body'
             return (x, rhs')
+    exits = es_joins st
 
     -- main working function. Goes through the RHS (tail-call positions only),
     -- checks if there are no more recursive calls, if so, abstracts over
@@ -87,7 +89,7 @@ exitify in_scope pairs =
 
     go :: [Var]           -- ^ variables to abstract over
        -> CoreExprWithFVs -- ^ current expression in tail position
-       -> State [(Id, CoreExpr)] CoreExpr
+       -> ExitifyM CoreExpr
 
     go captured ann_e
         -- Do not touch an expression that is already a join call with no free variables
@@ -175,8 +177,8 @@ exitify in_scope pairs =
 --  * any exit join points created so far.
 mkExitJoinId :: InScopeSet -> Type -> JoinArity -> ExitifyM JoinId
 mkExitJoinId in_scope ty join_arity = do
-    fs <- get
-    let avoid = in_scope `extendInScopeSetList` (map fst fs)
+    st <- get
+    let avoid = in_scope `extendInScopeSetList` (map fst (es_joins st))
                          `extendInScopeSet` exit_id_tmpl -- just cosmetics
     return (uniqAway avoid exit_id_tmpl)
   where
@@ -190,13 +192,24 @@ mkExitJoinId in_scope ty join_arity = do
                , occ_int_cxt = False
                , occ_tail = AlwaysTailCalled join_arity }
 
+-- Adds a new exit join point
+-- (or re-uses an existing one)
 addExit :: InScopeSet -> Type -> JoinArity -> CoreExpr -> ExitifyM JoinId
 addExit in_scope ty join_arity rhs = do
-    -- Pick a suitable name
-    v <- mkExitJoinId in_scope ty join_arity
-    fs <- get
-    put ((v,rhs):fs)
-    return v
-
-
-type ExitifyM =  State [(JoinId, CoreExpr)]
+    st <- get
+    case lookupTM rhs (es_map st) of
+        Just v -> return v
+        Nothing -> do
+            -- Pick a suitable name
+            v <- mkExitJoinId in_scope ty join_arity
+            st <- get
+            put (st { es_joins = (v,rhs) : es_joins st
+                    , es_map = insertTM rhs v (es_map st)
+                    })
+            return v
+
+data ExitifyState = ExitifyState { es_joins :: [(JoinId, CoreExpr)]
+                                 , es_map :: CoreMap JoinId
+                                 }
+
+type ExitifyM = State ExitifyState



More information about the ghc-commits mailing list