[commit: ghc] wip/T14068: Implement loopification for local bindings (#14068) (29a03ad)
git at git.haskell.org
git at git.haskell.org
Tue Aug 1 15:14:18 UTC 2017
Repository : ssh://git@git.haskell.org/ghc
On branch : wip/T14068
Link : http://ghc.haskell.org/trac/ghc/changeset/29a03ad7cc5734033bb1ccca1ca8c56a48ffeef3/ghc
>---------------------------------------------------------------
commit 29a03ad7cc5734033bb1ccca1ca8c56a48ffeef3
Author: Joachim Breitner <mail at joachim-breitner.de>
Date: Tue Aug 1 10:36:32 2017 -0400
Implement loopification for local bindings (#14068)
This is a relatively prelimary version. I am sure there is a huge number
of invariants that this breaks, and conditions that I am not checking
etc. I do not even know if the simplifier is the right place to
implement this.
But it works in this simple case:
module T14068 where
foo p f k =
let bar a = if p a then bar (f a) else a
in k bar
so we can iterate from here.
>---------------------------------------------------------------
29a03ad7cc5734033bb1ccca1ca8c56a48ffeef3
compiler/coreSyn/CoreOpt.hs | 34 +++++++++++++++++++++++++++-------
compiler/simplCore/Simplify.hs | 17 ++++++++++++++++-
2 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/compiler/coreSyn/CoreOpt.hs b/compiler/coreSyn/CoreOpt.hs
index 4a19605..0dae086 100644
--- a/compiler/coreSyn/CoreOpt.hs
+++ b/compiler/coreSyn/CoreOpt.hs
@@ -10,6 +10,7 @@ module CoreOpt (
-- ** Join points
joinPointBinding_maybe, joinPointBindings_maybe,
+ loopificationJoinPointBinding_maybe ,
-- ** Predicates on expressions
exprIsConApp_maybe, exprIsLiteral_maybe, exprIsLambda_maybe,
@@ -642,22 +643,41 @@ joinPointBinding_maybe bndr rhs
= Just (bndr, rhs)
| AlwaysTailCalled join_arity <- tailCallInfo (idOccInfo bndr)
- , not (bad_unfolding join_arity (idUnfolding bndr))
+ , not (badUnfoldingForJoin join_arity bndr)
, (bndrs, body) <- etaExpandToJoinPoint join_arity rhs
= Just (bndr `asJoinId` join_arity, mkLams bndrs body)
| otherwise
= Nothing
+-- | like joinPointBinding_maybe, but looks for RecursiveTailCalled
+loopificationJoinPointBinding_maybe :: InBndr -> InExpr -> Maybe (InBndr, InExpr)
+loopificationJoinPointBinding_maybe bndr rhs
+ | not (isId bndr)
+ = Nothing
+
+ | isJoinId bndr
+ = Nothing -- do not loopificate again
+
+ | RecursiveTailCalled join_arity <- tailCallInfo (idOccInfo bndr)
+ , not (badUnfoldingForJoin join_arity bndr)
+ , (bndrs, body) <- etaExpandToJoinPoint join_arity rhs
+ = Just (bndr `asJoinId` join_arity, mkLams bndrs body)
+
+ | otherwise
+ = Nothing
+
+-- | badUnfoldingForJoin returns True if we should /not/ convert a non-join-id
+-- into a join-id, even though it is AlwaysTailCalled
+-- See Note [Join points and INLINE pragmas]
+badUnfoldingForJoin :: JoinArity -> Id -> Bool
+badUnfoldingForJoin join_arity bndr = bad_unfolding (idUnfolding bndr)
where
- -- bad_unfolding returns True if we should /not/ convert a non-join-id
- -- into a join-id, even though it is AlwaysTailCalled
- -- See Note [Join points and INLINE pragmas]
- bad_unfolding join_arity (CoreUnfolding { uf_src = src, uf_tmpl = rhs })
+ bad_unfolding (CoreUnfolding { uf_src = src, uf_tmpl = rhs })
= isStableSource src && join_arity > joinRhsArity rhs
- bad_unfolding _ (DFunUnfolding {})
+ bad_unfolding (DFunUnfolding {})
= True
- bad_unfolding _ _
+ bad_unfolding _
= False
joinPointBindings_maybe :: [(InBndr, InExpr)] -> Maybe [(InBndr, InExpr)]
diff --git a/compiler/simplCore/Simplify.hs b/compiler/simplCore/Simplify.hs
index 1fc9112..51b93ff 100644
--- a/compiler/simplCore/Simplify.hs
+++ b/compiler/simplCore/Simplify.hs
@@ -36,7 +36,8 @@ import CoreUnfold
import CoreUtils
import CoreArity
import CoreOpt ( pushCoTyArg, pushCoValArg
- , joinPointBinding_maybe, joinPointBindings_maybe )
+ , joinPointBinding_maybe, joinPointBindings_maybe
+ , loopificationJoinPointBinding_maybe )
--import PrimOp ( tagToEnumKey ) -- temporalily commented out. See #8326
import Rules ( mkRuleInfo, lookupRule, getRules )
--import TysPrim ( intPrimTy ) -- temporalily commented out. See #8326
@@ -1637,6 +1638,7 @@ simplRecE :: SimplEnv
-- simplRecE is used for
-- * non-top-level recursive lets in expressions
simplRecE env pairs body cont
+
| Just pairs' <- joinPointBindings_maybe pairs
= do { (env1, cont') <- prepareJoinCont env cont
; let bndrs' = map fst pairs'
@@ -1647,6 +1649,19 @@ simplRecE env pairs body cont
; env3 <- simplRecBind env2 NotTopLevel (Just cont') pairs'
; simplExprF env3 body cont' }
+ -- Is this a tail-recursive function that we want to loopify? Then
+ -- lets loopify it and re-analyse.
+ | [(bndr,rhs)] <- pairs
+ , Just (join_bndr, join_rhs) <- loopificationJoinPointBinding_maybe bndr rhs
+ , let Just arity = isJoinId_maybe join_bndr
+ = do { let (join_params, _join_body) = collectNBinders arity join_rhs
+ ; let bndr' = zapFragileIdInfo bndr -- TODO: What do we have to zap here?
+ ; let rhs' = mkLams join_params $
+ mkLetRec [(join_bndr,join_rhs)] $
+ mkVarApps (Var join_bndr) join_params
+ ; simplNonRecE env bndr' (rhs', env) ([], body) cont
+ }
+
| otherwise
= do { let bndrs = map fst pairs
; MASSERT(all (not . isJoinId) bndrs)
More information about the ghc-commits
mailing list