Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch :
http://hackage.haskell.org/trac/ghc/changeset/021e35b8b53cf9297de3ecb963689a4d8109b91e >--------------------------------------------------------------- commit 021e35b8b53cf9297de3ecb963689a4d8109b91e Author: Max Bolingbroke <batterseapo...@hotmail.com> Date: Thu Apr 19 23:29:28 2012 +0100 Mark lambda contexts and be selective about what MSG floats from them >--------------------------------------------------------------- compiler/supercompile/Supercompile/Drive/MSG.hs | 39 ++++++++++++++--------- 1 files changed, 24 insertions(+), 15 deletions(-) diff --git a/compiler/supercompile/Supercompile/Drive/MSG.hs b/compiler/supercompile/Supercompile/Drive/MSG.hs index 046b154..7eb436b 100644 --- a/compiler/supercompile/Supercompile/Drive/MSG.hs +++ b/compiler/supercompile/Supercompile/Drive/MSG.hs @@ -68,10 +68,26 @@ instance Monad MSG' where type MSG' = Either String --- Information on the context which we are currently in (FIXME: currently unused) +-- Information on the context which we are currently in data MSGEnv = MSGEnv { + msgLostWorkSharing :: Bool } +msgLoseWorkSharing :: MSG a -> MSG a +msgLoseWorkSharing mx = MSG $ \e -> unMSG mx (e { msgLostWorkSharing = True }) + +-- I'm not sure if we want to float arbitrary stuff out of lambdas. Doing so does reduce +-- worst case allocation behaviour, but it does so at the cost of increased upfront allocations +-- and GC lifetimes. +-- +-- At the moment my poor compromise is to only float out cheap looking stuff. +msgCheckFloatable :: Bool -> Bool -> MSG () +msgCheckFloatable cheap_l cheap_r + | cheap_l, cheap_r = return () + | otherwise = MSG $ \e s -> if msgLostWorkSharing e + then Left "msgCheckFloatable" + else Right (s, ()) + -- We want to create as few new "common" vars as possible when MSGing. This state helps to achieve this: -- * When MSG encounters the same pair of two (heap or stack bound) things, we reuse the same "common" var -- to refer to them. @@ -162,7 +178,7 @@ newtype MSG a = MSG { unMSG :: MSGEnv -> MSGState -> MSG' (MSGState, a) } -- Don't need to specify MSGEnv because every site that needs to run a MSG -- computation occurs in basically the same context: runMSG :: MSG a -> MSGState -> MSG' (MSGState, a) -runMSG mx = unMSG mx (MSGEnv {}) +runMSG mx = unMSG mx (MSGEnv { msgLostWorkSharing = False }) instance Functor MSG where fmap = liftM @@ -293,6 +309,7 @@ msgAnned anned f a_l a_r = liftM (anned (annedTag a_r)) $ f (annedTag a_l) (anne msgQA, msgQA' :: RnEnv2 -> Tag -> QA -> Tag -> QA -> MSG QA msgQA rn2 tg_l qa_l tg_r qa_r = msgQA' rn2 tg_l qa_l tg_r qa_r `mplus` do guardFloatable "msgQA" qaFreeVars rn2 qa_l qa_r + -- NB: a QA is always cheap, so no floatability check liftM Question $ msgGeneraliseTerm rn2 (annedTerm tg_l (qaToAnnedTerm' (rnInScopeSet rn2) qa_l)) (annedTerm tg_r (qaToAnnedTerm' (rnInScopeSet rn2) qa_r)) msgQA' rn2 _ (Question x_l') _ (Question x_r') = liftM Question $ msgVar rn2 x_l' x_r' @@ -361,6 +378,7 @@ msgCoercion' _ _ _ = fail "msgCoercion" msgTerm :: RnEnv2 -> AnnedTerm -> AnnedTerm -> MSG AnnedTerm msgTerm rn2 e_l e_r = msgAnned annedTerm (msgTerm' rn2) e_l e_r `mplus` do guardFloatable "msgTerm" annedTermFreeVars rn2 e_l e_r + msgCheckFloatable (termIsCheap e_l) (termIsCheap e_r) liftM (fmap Var . annedVar (annedTag e_r)) $ msgGeneraliseTerm rn2 e_l e_r -- Right biased -- TODO: allow lets on only one side? Useful for msging e.g. (let x = 2 in y + x) with (z + 2) @@ -381,12 +399,13 @@ msgTerm' _ _ _ _ _ = fail "msgTerm" msgValue :: RnEnv2 -> Tag -> AnnedValue -> Tag -> AnnedValue -> MSG AnnedValue msgValue rn2 tg_l v_l tg_r v_r = msgValue' rn2 v_l v_r `mplus` do guardFloatable "msgValue" annedValueFreeVars' rn2 v_l v_r + -- NB: values are always cheap, so no floatability check liftM Indirect $ msgGeneraliseTerm rn2 (fmap Value $ annedValue tg_l v_l) (fmap Value $ annedValue tg_r v_r) msgValue' :: RnEnv2 -> AnnedValue -> AnnedValue -> MSG AnnedValue msgValue' rn2 (Indirect x_l) (Indirect x_r) = liftM Indirect $ msgVar rn2 x_l x_r -msgValue' rn2 (TyLambda a_l e_l) (TyLambda a_r e_r) = msgTyVarBndr TyLambda rn2 a_l a_r $ \rn2 -> msgTerm rn2 e_l e_r -msgValue' rn2 (Lambda x_l e_l) (Lambda x_r e_r) = msgIdCoVarBndr Lambda rn2 x_l x_r $ \rn2 -> msgTerm rn2 e_l e_r +msgValue' rn2 (TyLambda a_l e_l) (TyLambda a_r e_r) = msgTyVarBndr TyLambda rn2 a_l a_r $ \rn2 -> msgTerm rn2 e_l e_r +msgValue' rn2 (Lambda x_l e_l) (Lambda x_r e_r) = msgIdCoVarBndr Lambda rn2 x_l x_r $ \rn2 -> msgLoseWorkSharing (msgTerm rn2 e_l e_r) msgValue' rn2 (Data dc_l tys_l cos_l xs_l) (Data dc_r tys_r cos_r xs_r) = guard "msgValue: datacon" (dc_l == dc_r) >> liftM3 (Data dc_r) (zipWithEqualM (msgType rn2) tys_l tys_r) (zipWithEqualM (msgCoercion rn2) cos_l cos_r) (zipWithEqualM (msgVar rn2) xs_l xs_r) msgValue' _ (Literal l_l) (Literal l_r) = guard "msgValue: literal" (l_l == l_r) >> return (Literal l_r) msgValue' rn2 (Coercion co_l) (Coercion co_r) = liftM Coercion $ msgCoercion rn2 co_l co_r @@ -423,16 +442,6 @@ msgIdCoVarBndrFlexible f rn2 x_l x_r k = do x <- mx chosen_rn2 return (f x b) -{- -checkMSGLR :: Bool -> Id -> Id -> MSGLR -> MSG MSGLR -checkMSGLR lambdaish x_l x_r lr = case lr of - VarL _ e_r | x_r `elemVarSet` annedTermFreeVars e_r -> fail "checkMSGLR: deferred term mentioned rigid right variable" - | lambdaish, not (termIsCheap e_r) -> fail "checkMSGLR: expensive deferred (right) term escaping lambda" - VarR e_l _ | x_l `elemVarSet` annedTermFreeVars e_l -> fail "checkMSGLR: deferred term mentioned rigid left variable" - | lambdaish, not (termIsCheap e_l) -> fail "checkMSGLR: expensive deferred (left) term escaping lambda" - _ -> return lr --} - msgIdCoVarBndr' :: RnEnv2 -> Id -> Id -> (RnEnv2, RnEnv2 -> MSG Id) msgIdCoVarBndr' init_rn2 x_l x_r = (pprTraceSC "msgIdCoVarBndr'" (ppr (x_l, x_r)) init_rn2', \rn2 -> msgIdCoVarBndrExtras rn2 x x_l x_r) where (init_rn2', x) = rnBndr2' init_rn2 x_l x_r @@ -483,7 +492,7 @@ msgCore :: RnEnv2 -> Core.CoreExpr -> Core.CoreExpr -> MSG Core.CoreExpr msgCore rn2 (Core.Var x_l) (Core.Var x_r) = liftM Core.Var $ msgVar rn2 x_l x_r msgCore _ (Core.Lit l_l) (Core.Lit l_r) = guard "msgCore: Lit" (l_l == l_r) >> return (Core.Lit l_r) msgCore rn2 (Core.App e1_l e2_l) (Core.App e1_r e2_r) = liftM2 Core.App (msgCore rn2 e1_l e1_r) (msgCore rn2 e2_l e2_r) -msgCore rn2 (Core.Lam x_l e_l) (Core.Lam x_r e_r) = msgVarBndr Core.Lam rn2 x_l x_r $ \rn2 -> msgCore rn2 e_l e_r +msgCore rn2 (Core.Lam x_l e_l) (Core.Lam x_r e_r) = msgVarBndr Core.Lam rn2 x_l x_r $ \rn2 -> (if isId x_r then msgLoseWorkSharing else id) $ msgCore rn2 e_l e_r msgCore rn2 (Core.Let (Core.NonRec x_l e1_l) e2_l) (Core.Let (Core.NonRec x_r e1_r) e2_r) = liftM2 (\e1 (x, e2) -> Core.Let (Core.NonRec x e1) e2) (msgCore rn2 e1_l e1_r) $ msgVarBndr (,) rn2 x_l x_r $ \rn2 -> msgCore rn2 e2_l e2_r msgCore rn2 (Core.Let (Core.Rec xes_l) e_l) (Core.Let (Core.Rec xes_r) e_r) _______________________________________________ Cvs-ghc mailing list Cvs-ghc@haskell.org http://www.haskell.org/mailman/listinfo/cvs-ghc