Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch :
http://hackage.haskell.org/trac/ghc/changeset/4cf0709a0680d3b091a03f67588597526259acc1 >--------------------------------------------------------------- commit 4cf0709a0680d3b091a03f67588597526259acc1 Author: Max Bolingbroke <batterseapo...@hotmail.com> Date: Thu Mar 15 12:00:42 2012 +0000 In the evaluator, trim stack frames that are unreachable due to bottoming Ids >--------------------------------------------------------------- .../Supercompile/Evaluator/Evaluate.hs | 41 +++++++++++++++++++- .../supercompile/Supercompile/Evaluator/Syntax.hs | 5 ++- compiler/supercompile/Supercompile/Utilities.hs | 6 ++- 3 files changed, 49 insertions(+), 3 deletions(-) diff --git a/compiler/supercompile/Supercompile/Evaluator/Evaluate.hs b/compiler/supercompile/Supercompile/Evaluator/Evaluate.hs index d0e1f71..1eb89bf 100644 --- a/compiler/supercompile/Supercompile/Evaluator/Evaluate.hs +++ b/compiler/supercompile/Supercompile/Evaluator/Evaluate.hs @@ -17,13 +17,14 @@ import qualified Data.Map as M import qualified CoreSyn as CoreSyn import CoreUnfold (exprIsConApp_maybe) -import Coercion (liftCoSubstWith, coercionKind, isReflCo) +import Coercion (liftCoSubstWith, coercionKind, isReflCo, mkUnsafeCo) import TyCon import Type import PrelRules import Id import DataCon import Pair +import Demand (splitStrictSig, isBotRes) evaluatePrim :: InScopeSet -> Tag -> PrimOp -> [Type] -> [Answer] -> Maybe (Anned Answer) @@ -167,6 +168,13 @@ step' normalising ei_state = {-# SCC "step'" #-} | not (dUPLICATE_VALUES_EVALUATOR && normalising) , Just anned_a <- lookupAnswer (Heap h ids) x' -- NB: don't unwind *immediately* because we want that changing a Var into a Value in an empty stack is seen as a reduction 'step' = do { (deeds, a) <- prepareAnswer deeds x' (annee anned_a); return (deeds, Heap h ids, k, annedAnswerToInAnnedTerm ids $ annedAnswer (annedTag anned_a) a) } + -- Try to trim the stack if the Id is guaranteed to bottom out after a certain number of arguments + -- This is really amazingly important because so many case branches bottom out in at least one branch, + -- and we can save supercompiling big case nests if we trim them out eagerly. + | Just (ds, res_d) <- fmap splitStrictSig $ idStrictness_maybe x' + , isBotRes res_d + , Just (h_extra, k) <- trimUnreachable (length ds) (idType x') k + = Just (deeds, Heap (h `M.union` h_extra) ids, k, renamedTerm (annedTerm tg (Var x'))) | otherwise = do hb <- M.lookup x' h in_e <- heapBindingTerm hb @@ -180,6 +188,37 @@ step' normalising ei_state = {-# SCC "step'" #-} kf `Car` _ | Update y' <- tagee kf -> (deeds, Heap (M.insert x' (internallyBound (mkIdentityRenaming (unitVarSet y'), annedTerm (tag kf) (Var y'))) h) ids, k, in_e) _ -> (deeds, Heap (M.delete x' h) ids, Tagged tg (Update x') `Car` k, in_e) + -- TODO: this function totally ignores deeds + trimUnreachable :: Int -- Number of value arguments needed before evaluation bottoms out + -> Type -- Type of the possibly-bottoming thing in the hole + -> Stack -- Stack consuming the hole + -> Maybe (PureHeap, -- Heap bindings arising from any update frames we trimmed off + Stack) -- Trimmed stack (strictly "less" than the input one -- not necessarily shorter since we will replace e.g. a trailing Scrutinise with a Cast) + trimUnreachable = go + where + -- Ran out of stack: even if n == 0 we don't want to + -- trim the stack in these cases because we musn't return + -- Just if the tail of the stack is already trivial: doing + -- so would risk non-termination + go _ _ (Loco _) = Nothing + go _ _ (Tagged _ (CastIt _) `Car` Loco _) = Nothing + -- Got some non-trivial stack that is unreachable due to bottomness: kill it + go 0 hole_ty k@(Tagged cast_tg _ `Car` _) = Just $ + trainFoldl' (\(!hole_ty, !h) (Tagged tg kf) -> (stackFrameType' kf hole_ty, case kf of Update x' -> M.insert x' (internallyBound (renamedTerm (annedTerm tg (Var x')))) h; _ -> h)) + (\(!overall_ty, !h) gen -> (h, (if hole_ty `eqType` overall_ty then id else (Tagged cast_tg (CastIt (mkUnsafeCo hole_ty overall_ty)) `Car`)) $ Loco gen)) (hole_ty, M.empty) k + -- Haven't yet reached a bottom, but we might get enough arguments to reach + -- one in the future, so keep going + go n hole_ty (kf `Car` k) = mb_n' >>= \n' -> liftM (second (kf `Car`)) $ go n' (stackFrameType kf hole_ty) k + where mb_n' = case tagee kf of + TyApply _ -> Just n + CoApply _ -> Just (n - 1) + Apply _ -> Just (n - 1) + Scrutinise _ _ _ -> Nothing + PrimApply _ _ _ _ -> Nothing + StrictLet _ _ -> Nothing + Update _ -> Just n + CastIt _ -> Just n + -- Deal with a value at the top of the stack unwind :: Deeds -> Heap -> Stack -> Tag -> Answer -> Maybe UnnormalisedState unwind deeds h k tg_v a = unconsTrain k >>= \(kf, k) -> case tagee kf of diff --git a/compiler/supercompile/Supercompile/Evaluator/Syntax.hs b/compiler/supercompile/Supercompile/Evaluator/Syntax.hs index ebaf92e..fba773d 100644 --- a/compiler/supercompile/Supercompile/Evaluator/Syntax.hs +++ b/compiler/supercompile/Supercompile/Evaluator/Syntax.hs @@ -282,7 +282,10 @@ stackType :: Stack -> Type -> Type stackType k ty = trainCarFoldl' (flip stackFrameType) ty k stackFrameType :: Tagged StackFrame -> Type -> Type -stackFrameType kf hole_ty = case tagee kf of +stackFrameType = stackFrameType' . tagee + +stackFrameType' :: StackFrame -> Type -> Type +stackFrameType' kf hole_ty = case kf of TyApply ty -> hole_ty `applyTy` ty CoApply co -> hole_ty `applyFunTy` coercionType co Apply x -> hole_ty `applyFunTy` idType x diff --git a/compiler/supercompile/Supercompile/Utilities.hs b/compiler/supercompile/Supercompile/Utilities.hs index 4ea1b2c..cbefcf0 100644 --- a/compiler/supercompile/Supercompile/Utilities.hs +++ b/compiler/supercompile/Supercompile/Utilities.hs @@ -661,6 +661,10 @@ trainToList :: Train a b -> ([a], b) trainToList (Car a abs) = first (a:) (trainToList abs) trainToList (Loco b) = ([], b) +trainLoco :: Train a b -> b +trainLoco (Car _ abs) = trainLoco abs +trainLoco (Loco b) = b + trainCars :: Train a b -> [a] trainCars (Car a abs) = a : trainCars abs trainCars (Loco _) = [] @@ -669,7 +673,7 @@ trainCarFoldl' :: (c -> a -> c) -> c -> Train a b -> c trainCarFoldl' f_car = trainFoldl' f_car (\s _a -> s) {-# INLINE trainFoldl' #-} -trainFoldl' :: (c -> a -> c) -> (c -> b -> c) -> c -> Train a b -> c +trainFoldl' :: (c -> a -> c) -> (c -> b -> d) -> c -> Train a b -> d trainFoldl' f_car f_loco = go where go s (Loco b) = s `seq` f_loco s b go s (Car a abs) = s `seq` go (f_car s a) abs _______________________________________________ Cvs-ghc mailing list Cvs-ghc@haskell.org http://www.haskell.org/mailman/listinfo/cvs-ghc