Repository : ssh://darcs.haskell.org//srv/darcs/ghc On branch :
http://hackage.haskell.org/trac/ghc/changeset/4f6c5f54855fcfc37197a6e0267e0aa2268af6f5 >--------------------------------------------------------------- commit 4f6c5f54855fcfc37197a6e0267e0aa2268af6f5 Author: Max Bolingbroke <batterseapo...@hotmail.com> Date: Tue Mar 20 17:04:25 2012 +0000 Fix intensely stupid bug in binding partitioning >--------------------------------------------------------------- compiler/supercompile/Supercompile.hs | 35 ++++++++++++++++++-------------- 1 files changed, 20 insertions(+), 15 deletions(-) diff --git a/compiler/supercompile/Supercompile.hs b/compiler/supercompile/Supercompile.hs index 8a38c66..7e65989 100644 --- a/compiler/supercompile/Supercompile.hs +++ b/compiler/supercompile/Supercompile.hs @@ -1,5 +1,7 @@ module Supercompile (supercompileProgram, supercompileProgramSelective) where +#include "HsVersions.h" + -- FIXME: I need to document the basis on which I push down unlifted heap bindings (they are all values, IIRC) -- TODO: -- * Why does the supercompiler not match as much as it should? (e.g. Interpreter, UInterpreter) @@ -44,6 +46,8 @@ import TyCon (newTyConCo_maybe) import qualified Data.Map as M +type FlatCoreBinds = [(Id, CoreExpr)] + -- Split input bindings into two lists: -- 1) CoreBinds binding variables with at least one binder marked by the predicate, -- and any CoreBinds that those CoreBinds transitively refer to @@ -52,28 +56,28 @@ import qualified Data.Map as M -- -- NB: assumes no-shadowing at the top level. I don't want to have to rename stuff to -- commute CoreBinds... -partitionBinds :: (Id -> Bool) -> [CoreBind] -> ([CoreBind], [CoreBind]) +partitionBinds :: (Id -> Bool) -> FlatCoreBinds -> (FlatCoreBinds, FlatCoreBinds) partitionBinds should_sc initial_binds = go initial_inside initial_undecided where - (initial_inside, initial_undecided) = partition (any should_sc . bindersOf) initial_binds + (initial_inside, initial_undecided) = partition (should_sc . fst) initial_binds - go :: [CoreBind] -> [CoreBind] -> ([CoreBind], [CoreBind]) + go :: FlatCoreBinds -> FlatCoreBinds -> (FlatCoreBinds, FlatCoreBinds) go inside undecided | null inside' = (inside, undecided) | otherwise = first (inside ++) $ go inside' undecided' where -- Move anything inside that is referred to by a binding that was moved inside last round inside_fvs = coreBindsFVs inside - (inside', undecided') = partition (\b -> any (`elemVarSet` inside_fvs) (bindersOf b)) undecided + (inside', undecided') = partition (\(x, _) -> x `elemVarSet` inside_fvs) undecided -coreBindsFVs :: [CoreBind] -> S.FreeVars -coreBindsFVs bs = unionVarSets [fvs | b <- bs, fvs <- map S.idFreeVars (bindersOf b) ++ map exprFreeVars (rhssOfBind b)] +coreBindsFVs :: FlatCoreBinds -> S.FreeVars +coreBindsFVs bs = unionVarSets [S.idFreeVars x `unionVarSet` exprFreeVars e | (x, e) <- bs] -coreBindsToCoreTerm :: (Id -> Bool) -> [CoreBind] -> (CoreExpr, Var -> [(Var, CoreExpr)]) +coreBindsToCoreTerm :: (Id -> Bool) -> FlatCoreBinds -> (CoreExpr, Var -> FlatCoreBinds) coreBindsToCoreTerm should_sc binds = --pprTrace "coreBindsToCoreTerm" (ppr (bindersOfBinds binds, bindersOfBinds sc_binds, bindersOfBinds dont_sc_binds, dont_sc_binds_fvs, sc_xs_internal_xs, sc_xs, bindersOfBinds internal_sc_binds)) $ - (mkLets internal_sc_binds (mkLiftedVarTup sc_internal_xs), - \y -> [(x, mkLiftedTupleSelector sc_internal_xs internal_x (Var y)) | (x, internal_x) <- sc_xs_internal_xs] ++ flattenBinds dont_sc_binds) + (Let (Rec internal_sc_binds) (mkLiftedVarTup sc_internal_xs), + \y -> [(x, mkLiftedTupleSelector sc_internal_xs internal_x (Var y)) | (x, internal_x) <- sc_xs_internal_xs] ++ dont_sc_binds) where -- We put all the sc_binds into a local let, and use unboxed tuples to bind back to the top level the names of -- any of those sc_binds that are either exported *or* in the free variables of something from dont_sc_binds. @@ -96,13 +100,13 @@ coreBindsToCoreTerm should_sc binds -- -- My third attempt just encodes it as an unboxed tuple, which we contrive to buind at the top level by abstracting -- it over a useless arg of void representation. - (sc_binds, dont_sc_binds) = partitionBinds should_sc binds + (sc_binds, dont_sc_binds) = partitionBinds should_sc binds -- FIXME: experiment with just taking annotated binds, and relying on unfoldings for the rest (problematic for non-values, though!) dont_sc_binds_fvs = coreBindsFVs dont_sc_binds -- We should zap fragile information on the Ids' we use within the tuple selector. The reasons are: -- 1. They may be mutually inter-referring, and the binders of a "case" are not simultaneously brought into scope -- 2. For some reason, GHC seems to have trouble optimising (let x = y in x) to (y) if x has an unfolding. - zappedBindersOfBinds = map zapFragileIdInfo . bindersOfBinds + zappedBindersOfBinds = map (zapFragileIdInfo . fst) -- This is a sweet hack. Most of the top-level binders will be External names. It is a Bad Idea to locally-bind -- an External name, because several Externals with the same name but different uniques will generate clashing @@ -113,9 +117,7 @@ coreBindsToCoreTerm should_sc binds -- unique and b) the internality of these names will be carried down on the next simplifier run, so this works. -- The ice is thin, though! sc_xs = zappedBindersOfBinds sc_binds - internal_sc_binds = [case bind of NonRec x e -> NonRec (localiseInternaliseId x) e - Rec xes -> Rec (map (first localiseInternaliseId) xes) - | bind <- sc_binds] + internal_sc_binds = map (first localiseInternaliseId) sc_binds -- Decide which things we should export from the supercompiled term using a Church tuple. -- We need to export to the top level of the module those bindings that are *any* of: -- 1. Are exported by the module itself @@ -209,4 +211,7 @@ supercompileProgram binds = supercompileProgramSelective selector binds supercompileProgramSelective :: (Id -> Bool) -> [CoreBind] -> IO [CoreBind] supercompileProgramSelective should_sc binds = liftM (\e' -> [Rec $ (x, e') : rebuild x]) (supercompile e) where x = mkSysLocal (fsLit "sc") topUnique (exprType e) - (e, rebuild) = coreBindsToCoreTerm should_sc binds + -- NB: we assume no-shadowing at top level, which is probably reasonable + flat_binds = flattenBinds binds + (e, rebuild) = ASSERT(length (nub (map fst flat_binds)) == length flat_binds) + coreBindsToCoreTerm should_sc flat_binds _______________________________________________ Cvs-ghc mailing list Cvs-ghc@haskell.org http://www.haskell.org/mailman/listinfo/cvs-ghc