Hi, I attach a piece of code: it's part of my thesis, attempts to turn (strict) functions to catamorphisms (see the comment in the code). It compiles just fine with core lint and debug on, but when I add the call to cheapSimplify it produces a runtime error: [hsc: no threads to run: infinite loop or deadlock?] The funny thing is of course that the result is not even used, only printed with trace. Without the call to cheapSimplify it prints whatever it is expected to print. I did not tinker with simplExpr (which is called by cheapSimplify) or any other part of the compiler only added to it. I am using the original -- from someone's RPM -- 4.06 under SuSe 6.3. If you need all the code (it's three more files 2-300 lines each) to reproduce the error I'm happy to send it. Any ideas? Thanks, Laszlo
\begin{code} module Cataify ( cataify ) where #include "HsVersions.h" import CoreSyn import CoreUtils ( coreExprType ) import CoreUnfold ( certainlySmallEnoughToInline, calcUnfoldingGuidance ) import CmdLineOpts ( opt_D_dump_cataified, opt_UF_CreationThreshold , SwitchResult(..), SimplifierSwitch(..) ) import Id ( getInlinePragma, mkVanillaId, setInlinePragma ) import IdInfo ( InlinePragInfo(..) ) import TyCon ( TyCon, tyConTyVars ) import DataCon ( dataConArgTys, dataConName, DataCon ) import Simplify ( simplExpr ) import SimplMonad ( initSmpl, thenSmpl, mapSmpl, returnSmpl ) import CoreLint ( beginPass, endPass ) import OccName ( mkSrcVarOcc ) import Name ( mkDerivedName, getOccString ) import VarSet ( VarSet, emptyVarSet, mkVarSet ) import FastString ( mkFastString ) import List ( partition ) import Util ( only, sortLt ) import WFUtil import Outputable \end{code} \begin{code} cataify :: UniqSupply -> [CoreBind] -> IO [CoreBind] cataify us binds = do { beginPass "Cataify"; let { binds' = initUs_ us $ mapUs (walkBind (fusible_tcs, cataids, mapids)) others `thenUs` \ others' -> returnUs (concat others') }; -- endPass "Cataify" opt_D_dump_cataified (cbs ++ binds'); return ([Rec . flattenBinds $ (catas ++ binds')]); } where (catas, others) = partition (isCata . getFirstBdr) binds -- tycon is fusible *iff* there is a cata for it fusible_tcs = map (sortLt sortPredForTyCons . map tyConOfCataOrMap . bindersOf) $ catas cataids = bindersOfBinds catas mapids = bindersOfBinds . filter (isMap . getFirstBdr) $ others \end{code} f :: \/a .T t -> v f = /\ a \ t v. e => f_1 = /\ a \ z_1 .. z_n \ v.(\t.e) (C1 tyargs x_1 ... x_nm) ... f_n = /\ a \ z_1 .. z_n \ v.(\t.e) (Cn tyargs x_1 ... x_nm) f is split into as many functions as constructors of T has. v denotes an arbitrary number of arguments x_1...x_n are appropriately typed fresh variables z_1...z_n ditto, but their types are 'abstractified' (abstractTys) we can't generate the zs (new binders -- rhs of rules) here as we don't have all the bindings in a mutually recursive group i.e. we don't know how many rho's we need. So we do f_1 = /\ a \ v.(\t.e) (C1 tyargs x_1 ... x_nm) !!! zs need to be inserted between the type binders and v !!! \begin{code} cataifySplit :: ([[TyCon]], [Id], [Id]) -> [ (Id, CoreExpr) ] -> UniqSM [ CoreBind ] cataifySplit (ftcs, _, _) binds__ -- never_inline needs to be put back, but right now the -- buildified stuff is marked as never inline | any null argss__ -- all of them are functions {-|| never_inline fn_id-} || any (not . maybeFusible (concat ftcs) . head) argss__ -- all the first args are |fusible || any null bdrss__ -- we can get the arguments -- FIX ME: add that the number of functions in the mut rec group is -- exactly the same as the number of mut rec tycons. We don't -- know what to do with the extra functions. = trace (showSDoc (hcat [text "Failed: " <> ppr bdrs__ <+> ppr argss__])) $ returnUs [Rec binds__] | otherwise -- Do the business -- ASSUMPTION: the entire group is quantified over the same -- number of type variables = getUniquesUs (length . takeWhile (not . isId) $ (head bdrss)) `thenUs` \ tv_uniqs -> getUs `thenUs` \ supply -> let tvs = map myMkSysTyVar tv_uniqs tvtys = mkTyVarTys tvs newrhss = map (flip mkApps (map Type tvtys)) rhss insttys = snd3 . splitAlgTyConApp . head . fst . splitFunTys . coreExprType . head $ newrhss (us1, us2) = splitUniqSupply supply in setUs us1 `thenUs_` mapUs (mapUs (genConApp insttys)) dataconss `thenUs` \ lfuns -> let rexprs = cheapSimplify us2 emptyVarSet . concat . map (\ (e, a) -> map (mkApps e . flip (:) [] . snd) a) $ zip newrhss lfuns in trace (showSDoc (vcat [text "Attempted: " <> text (show (length tv_uniqs)) , ppr bdrs , ppr (map coreExprType newrhss) , ppr rexprs])) $ returnUs [Rec binds'] where -- the original binds are used because that doesn't require them -- to be sorted. The sort predicate assumes that the first -- argument is a splitAlgTyConApp-able -- DONT USE THESE names except for the guards: they are coming from the UNSORTED bindings (bdrs__, rhss__) = unzip binds__ (bdrss__, _) = unzip . map collectBinders $ rhss__ argss__ = map (fst . splitFunTys . snd . splitForAllTys . idType) bdrs__ -- END OF DONT USE -- Don't split something which is marked unconditionally NOINLINE never_inline fid = case getInlinePragma fid of IMustNotBeINLINEd False Nothing -> True other -> False -- Re-sort the bindings to make sure that ordering matches that of in Derive binds' = sortLt sortPredForBindings binds__ tc_group = map ( fst3 . splitAlgTyConApp . head . fst . splitFunTys . snd . splitForAllTys . idType . fst) $ binds' -- all the data constructors in the RIGHT order (tycons are sorted) dataconss = map tyConDataCons tc_group (bdrs, rhss) = unzip binds' (bdrss, _) = unzip . map collectBinders $ rhss genConApp :: [Type] -> DataCon -> UniqSM ([Id], CoreExpr) genConApp tys dcon = getUniquesUs (length argtys) `thenUs` \ uniqs -> let arg_ids = map (\ (u, t, n) -> mkSysLocal (mkFastString (name ++ "_" ++ show n)) u t) $ zip3 uniqs argtys [1..] in returnUs (arg_ids, mkConApp dcon (map Type tys ++ map Var arg_ids)) where argtys = dataConArgTys dcon tys name = lowercase . getOccString . dataConName $ dcon \end{code} \begin{code} cheapSimplify :: UniqSupply -> VarSet -> [CoreExpr] -> [CoreExpr] cheapSimplify supply varset exprs = case (initSmpl sw_chkr supply varset (\id -> True) (mapSmpl simplExpr exprs)) of (exprs', _) -> exprs' where sw_chkr (MaxSimplifierIterations _) = SwInt 1 sw_chkr (SimplInlinePhase _) = SwInt 1 sw_chkr SimplLetToCase = SwBool False sw_chkr DontApplyRules = SwBool False \end{code} \begin{code} walkBind :: ([[TyCon]], [Id], [Id]) -> CoreBind -> UniqSM [CoreBind] walkBind ids bind@(NonRec binder rhs) = walkExpr ids rhs `thenUs` \ new_rhs -> cataifySplit ids [ (binder, new_rhs) ] walkBind ids (Rec pairs) = mapUs (walkExpr ids) rhss `thenUs` \ new_rhss -> cataifySplit ids (zip bdrs new_rhss) where (bdrs, rhss) = unzip pairs walkExpr :: ([[TyCon]], [Id], [Id]) -> CoreExpr -> UniqSM CoreExpr walkExpr ids e@(Type _) = returnUs e walkExpr ids e@(Var _) = returnUs e walkExpr ids (Con con args) = mapUs (walkExpr ids) args `thenUs` \ args' -> returnUs (Con con args') walkExpr ids (Lam binder expr) = walkExpr ids expr `thenUs` \ new_expr -> returnUs (Lam binder new_expr) walkExpr ids (App f a) = walkExpr ids f `thenUs` \ new_f -> walkExpr ids a `thenUs` \ new_a -> returnUs (App new_f new_a) walkExpr ids (Note note expr) = walkExpr ids expr `thenUs` \ new_expr -> returnUs (Note note new_expr) walkExpr ids (Let bind expr) = walkBind ids bind `thenUs` \ intermediate_bind -> walkExpr ids expr `thenUs` \ new_expr -> returnUs (mkLets intermediate_bind new_expr) walkExpr ids (Case expr binder alts) = walkExpr ids expr `thenUs` \ new_expr -> mapUs walk_alt alts `thenUs` \ new_alts -> returnUs (Case new_expr binder new_alts) where walk_alt (con, binders, rhs) = walkExpr ids rhs `thenUs` \ new_rhs -> returnUs (con, binders, new_rhs) \end{code} The rewrite engine \begin{code} type RewriteRule = (CoreExpr, CoreExpr) type Trans a = a -> (a -> a) -> a -> a rewrite :: Trans CoreExpr -> (CoreExpr -> CoreExpr) rewrite sys term = rew term where rew = (\term -> sys term rew term) . distr rew distr f expr = case expr of Var x -> Var x Con con args -> Con con (map f args) App e1 e2 -> App (f e1) (f e2) Lam b e -> Lam b (f e) Let bind e -> Let (appToBind bind) (f e) Case e b alts -> Case (f e) b (map appToAlt alts) Note note e -> Note note (f e) Type t -> Type t where appToBind (NonRec b e) = NonRec b (f e) appToBind (Rec pairs) = Rec [ (b, f e) | (b, e) <- pairs ] appToAlt (con, bs, e) = (con, bs, f e) \end{code}