X-Git-Url: http://git.megacz.com/?a=blobdiff_plain;f=compiler%2Fvectorise%2FVectorise.hs;h=c53c638a1c7f69eeff040cc9a5fd76bbffa30427;hb=3a90968fac18bbf931420afff6ef866614ecdd7f;hp=29774d1ad38342b1808bee369920fdf4ff419357;hpb=f48c36d1f3f64570b44fae1737ad34f6ce98bd7d;p=ghc-hetmet.git diff --git a/compiler/vectorise/Vectorise.hs b/compiler/vectorise/Vectorise.hs index 29774d1..c53c638 100644 --- a/compiler/vectorise/Vectorise.hs +++ b/compiler/vectorise/Vectorise.hs @@ -1,268 +1,529 @@ + module Vectorise( vectorise ) where -#include "HsVersions.h" - import VectMonad +import VectUtils +import VectType +import VectCore -import DynFlags -import HscTypes +import HscTypes hiding ( MonadThings(..) ) -import CoreLint ( showPass, endPass ) +import Module ( PackageId ) import CoreSyn import CoreUtils +import CoreUnfold ( mkInlineRule ) +import MkCore ( mkWildCase ) import CoreFVs +import CoreMonad ( CoreM, getHscEnv ) +import DataCon import TyCon import Type -import TypeRep +import FamInstEnv ( extendFamInstEnvList ) import Var import VarEnv -import Name ( mkSysTvName ) -import NameEnv +import VarSet import Id +import OccName +import BasicTypes ( isLoopBreaker ) -import DsMonad hiding (mapAndUnzipM) - -import PrelNames +import Literal ( Literal, mkMachInt ) +import TysWiredIn +import TysPrim ( intPrimTy ) import Outputable import FastString -import Control.Monad ( liftM, liftM2, mapAndUnzipM ) +import Util ( zipLazy ) +import Control.Monad +import Data.List ( sortBy, unzip4 ) + +vectorise :: PackageId -> ModGuts -> CoreM ModGuts +vectorise backend guts = do + hsc_env <- getHscEnv + liftIO $ vectoriseIO backend hsc_env guts -vectorise :: HscEnv -> ModGuts -> IO ModGuts -vectorise hsc_env guts - | not (Opt_Vectorise `dopt` dflags) = return guts - | otherwise +vectoriseIO :: PackageId -> HscEnv -> ModGuts -> IO ModGuts +vectoriseIO backend hsc_env guts = do - showPass dflags "Vectorisation" eps <- hscEPS hsc_env let info = hptVectInfo hsc_env `plusVectInfo` eps_vect_info eps - Just (info', guts') <- initV hsc_env guts info (vectModule guts) - endPass dflags "Vectorisation" Opt_D_dump_vect (mg_binds guts') - return $ guts' { mg_vect_info = info' } - where - dflags = hsc_dflags hsc_env + Just (info', guts') <- initV backend hsc_env guts info (vectModule guts) + return (guts' { mg_vect_info = info' }) vectModule :: ModGuts -> VM ModGuts -vectModule guts = return guts +vectModule guts + = do + (types', fam_insts, tc_binds) <- vectTypeEnv (mg_types guts) + + let fam_inst_env' = extendFamInstEnvList (mg_fam_inst_env guts) fam_insts + updGEnv (setFamInstEnv fam_inst_env') + + -- dicts <- mapM buildPADict pa_insts + -- workers <- mapM vectDataConWorkers pa_insts + binds' <- mapM vectTopBind (mg_binds guts) + return $ guts { mg_types = types' + , mg_binds = Rec tc_binds : binds' + , mg_fam_inst_env = fam_inst_env' + , mg_fam_insts = mg_fam_insts guts ++ fam_insts + } + +vectTopBind :: CoreBind -> VM CoreBind +vectTopBind b@(NonRec var expr) + = do + (inline, expr') <- vectTopRhs var expr + var' <- vectTopBinder var inline expr' + hs <- takeHoisted + cexpr <- tryConvert var var' expr + return . Rec $ (var, cexpr) : (var', expr') : hs + `orElseV` + return b + +vectTopBind b@(Rec bs) + = do + (vars', _, exprs') <- fixV $ \ ~(_, inlines, rhss) -> + do + vars' <- sequence [vectTopBinder var inline rhs + | (var, ~(inline, rhs)) + <- zipLazy vars (zip inlines rhss)] + (inlines', exprs') <- mapAndUnzipM (uncurry vectTopRhs) bs + return (vars', inlines', exprs') + hs <- takeHoisted + cexprs <- sequence $ zipWith3 tryConvert vars vars' exprs + return . Rec $ zip vars cexprs ++ zip vars' exprs' ++ hs + `orElseV` + return b + where + (vars, exprs) = unzip bs + +-- NOTE: vectTopBinder *MUST* be lazy in inline and expr because of how it is +-- used inside of fixV in vectTopBind +vectTopBinder :: Var -> Inline -> CoreExpr -> VM Var +vectTopBinder var inline expr + = do + vty <- vectType (idType var) + var' <- liftM (`setIdUnfolding` unfolding) $ cloneId mkVectOcc var vty + defGlobalVar var var' + return var' + where + unfolding = case inline of + Inline arity -> mkInlineRule expr (Just arity) + DontInline -> noUnfolding + +vectTopRhs :: Var -> CoreExpr -> VM (Inline, CoreExpr) +vectTopRhs var expr + = closedV + $ do + (inline, vexpr) <- inBind var + $ vectPolyExpr (isLoopBreaker $ idOccInfo var) + (freeVars expr) + return (inline, vectorised vexpr) + +tryConvert :: Var -> Var -> CoreExpr -> VM CoreExpr +tryConvert var vect_var rhs + = fromVect (idType var) (Var vect_var) `orElseV` return rhs -- ---------------------------------------------------------------------------- -- Bindings -vectBndr :: Var -> VM (Var, Var) +vectBndr :: Var -> VM VVar vectBndr v = do - vty <- vectType (idType v) - lty <- mkPArrayTy vty + (vty, lty) <- vectAndLiftType (idType v) let vv = v `Id.setIdType` vty lv = v `Id.setIdType` lty updLEnv (mapTo vv lv) return (vv, lv) where - mapTo vv lv env = env { local_vars = extendVarEnv (local_vars env) v (Var vv, Var lv) } + mapTo vv lv env = env { local_vars = extendVarEnv (local_vars env) v (vv, lv) } -vectBndrIn :: Var -> VM a -> VM (Var, Var, a) +vectBndrNew :: Var -> FastString -> VM VVar +vectBndrNew v fs + = do + vty <- vectType (idType v) + vv <- newLocalVVar fs vty + updLEnv (upd vv) + return vv + where + upd vv env = env { local_vars = extendVarEnv (local_vars env) v vv } + +vectBndrIn :: Var -> VM a -> VM (VVar, a) vectBndrIn v p = localV $ do - (vv, lv) <- vectBndr v + vv <- vectBndr v x <- p - return (vv, lv, x) + return (vv, x) -vectBndrsIn :: [Var] -> VM a -> VM ([Var], [Var], a) +vectBndrNewIn :: Var -> FastString -> VM a -> VM (VVar, a) +vectBndrNewIn v fs p + = localV + $ do + vv <- vectBndrNew v fs + x <- p + return (vv, x) + +vectBndrsIn :: [Var] -> VM a -> VM ([VVar], a) vectBndrsIn vs p = localV $ do - (vvs, lvs) <- mapAndUnzipM vectBndr vs + vvs <- mapM vectBndr vs x <- p - return (vvs, lvs, x) + return (vvs, x) -- ---------------------------------------------------------------------------- -- Expressions -replicateP :: CoreExpr -> CoreExpr -> VM CoreExpr -replicateP expr len +vectVar :: Var -> VM VExpr +vectVar v = do - pa <- paOfType ty - rep <- builtin replicatePAVar - return $ mkApps (Var rep) [Type ty, pa, expr, len] - where - ty = exprType expr + r <- lookupVar v + case r of + Local (vv,lv) -> return (Var vv, Var lv) + Global vv -> do + let vexpr = Var vv + lexpr <- liftPD vexpr + return (vexpr, lexpr) + +vectPolyVar :: Var -> [Type] -> VM VExpr +vectPolyVar v tys + = do + vtys <- mapM vectType tys + r <- lookupVar v + case r of + Local (vv, lv) -> liftM2 (,) (polyApply (Var vv) vtys) + (polyApply (Var lv) vtys) + Global poly -> do + vexpr <- polyApply (Var poly) vtys + lexpr <- liftPD vexpr + return (vexpr, lexpr) + +vectLiteral :: Literal -> VM VExpr +vectLiteral lit + = do + lexpr <- liftPD (Lit lit) + return (Lit lit, lexpr) -capply :: (CoreExpr, CoreExpr) -> (CoreExpr, CoreExpr) -> VM (CoreExpr, CoreExpr) -capply (vfn, lfn) (varg, larg) +vectPolyExpr :: Bool -> CoreExprWithFVs -> VM (Inline, VExpr) +vectPolyExpr loop_breaker (_, AnnNote note expr) = do - apply <- builtin applyClosureVar - applyP <- builtin applyClosurePVar - return (mkApps (Var apply) [Type arg_ty, Type res_ty, vfn, varg], - mkApps (Var applyP) [Type arg_ty, Type res_ty, lfn, larg]) + (inline, expr') <- vectPolyExpr loop_breaker expr + return (inline, vNote note expr') +vectPolyExpr loop_breaker expr + = do + arity <- polyArity tvs + polyAbstract tvs $ \args -> + do + (inline, mono') <- vectFnExpr False loop_breaker mono + return (addInlineArity inline arity, + mapVect (mkLams $ tvs ++ args) mono') where - fn_ty = exprType vfn - (arg_ty, res_ty) = splitClosureTy fn_ty + (tvs, mono) = collectAnnTypeBinders expr + +vectExpr :: CoreExprWithFVs -> VM VExpr +vectExpr (_, AnnType ty) + = liftM vType (vectType ty) + +vectExpr (_, AnnVar v) = vectVar v -vectVar :: CoreExpr -> Var -> VM (CoreExpr, CoreExpr) -vectVar lc v = local v `orElseV` global v +vectExpr (_, AnnLit lit) = vectLiteral lit + +vectExpr (_, AnnNote note expr) + = liftM (vNote note) (vectExpr expr) + +vectExpr e@(_, AnnApp _ arg) + | isAnnTypeArg arg + = vectTyAppExpr fn tys where - local v = maybeV (readLEnv $ \env -> lookupVarEnv (local_vars env) v) - global v = do - vexpr <- maybeV (readGEnv $ \env -> lookupVarEnv (global_vars env) v) - lexpr <- replicateP vexpr lc - return (vexpr, lexpr) - -vectExpr :: CoreExpr -> CoreExprWithFVs -> VM (CoreExpr, CoreExpr) -vectExpr lc (_, AnnType ty) - = do - vty <- vectType ty - return (Type vty, Type vty) -vectExpr lc (_, AnnVar v) = vectVar lc v -vectExpr lc (_, AnnLit lit) + (fn, tys) = collectAnnTypeArgs e + +vectExpr (_, AnnApp (_, AnnVar v) (_, AnnLit lit)) + | Just con <- isDataConId_maybe v + , is_special_con con = do - let vexpr = Lit lit - lexpr <- replicateP vexpr lc + let vexpr = App (Var v) (Lit lit) + lexpr <- liftPD vexpr return (vexpr, lexpr) -vectExpr lc (_, AnnNote note expr) - = do - (vexpr, lexpr) <- vectExpr lc expr - return (Note note vexpr, Note note lexpr) -vectExpr lc (_, AnnApp fn arg) + where + is_special_con con = con `elem` [intDataCon, floatDataCon, doubleDataCon] + + +vectExpr (_, AnnApp fn arg) = do - fn' <- vectExpr lc fn - arg' <- vectExpr lc arg - capply fn' arg' -vectExpr lc (_, AnnCase expr bndr ty alts) - = panic "vectExpr: case" -vectExpr lc (_, AnnLet (AnnNonRec bndr rhs) body) + arg_ty' <- vectType arg_ty + res_ty' <- vectType res_ty + fn' <- vectExpr fn + arg' <- vectExpr arg + mkClosureApp arg_ty' res_ty' fn' arg' + where + (arg_ty, res_ty) = splitFunTy . exprType $ deAnnotate fn + +vectExpr (_, AnnCase scrut bndr ty alts) + | Just (tycon, ty_args) <- splitTyConApp_maybe scrut_ty + , isAlgTyCon tycon + = vectAlgCase tycon ty_args scrut bndr ty alts + where + scrut_ty = exprType (deAnnotate scrut) + +vectExpr (_, AnnLet (AnnNonRec bndr rhs) body) = do - (vrhs, lrhs) <- vectExpr lc rhs - (vbndr, lbndr, (vbody, lbody)) <- vectBndrIn bndr (vectExpr lc body) - return (Let (NonRec vbndr vrhs) vbody, - Let (NonRec lbndr lrhs) lbody) -vectExpr lc (_, AnnLet (AnnRec prs) body) + vrhs <- localV . inBind bndr . liftM snd $ vectPolyExpr False rhs + (vbndr, vbody) <- vectBndrIn bndr (vectExpr body) + return $ vLet (vNonRec vbndr vrhs) vbody + +vectExpr (_, AnnLet (AnnRec bs) body) = do - (vbndrs, lbndrs, (vrhss, vbody, lrhss, lbody)) <- vectBndrsIn bndrs vect - return (Let (Rec (zip vbndrs vrhss)) vbody, - Let (Rec (zip lbndrs lrhss)) lbody) + (vbndrs, (vrhss, vbody)) <- vectBndrsIn bndrs + $ liftM2 (,) + (zipWithM vect_rhs bndrs rhss) + (vectExpr body) + return $ vLet (vRec vbndrs vrhss) vbody where - (bndrs, rhss) = unzip prs - - vect = do - (vrhss, lrhss) <- mapAndUnzipM (vectExpr lc) rhss - (vbody, lbody) <- vectExpr lc body - return (vrhss, vbody, lrhss, lbody) -vectExpr lc (_, AnnLam bndr body) - | isTyVar bndr - = do - pa_ty <- paArgType' (TyVarTy bndr) (tyVarKind bndr) - pa_var <- newLocalVar FSLIT("dPA") pa_ty - (vbody, lbody) <- localV - $ do - extendTyVarPA bndr (Var pa_var) - -- FIXME: what about shadowing here (bndr in lc)? - vectExpr lc body - return (mkLams [bndr, pa_var] vbody, - mkLams [bndr, pa_var] lbody) + (bndrs, rhss) = unzip bs + + vect_rhs bndr rhs = localV + . inBind bndr + . liftM snd + $ vectPolyExpr (isLoopBreaker $ idOccInfo bndr) rhs + +vectExpr e@(_, AnnLam bndr _) + | isId bndr = liftM snd $ vectFnExpr True False e +{- +onlyIfV (isEmptyVarSet fvs) (vectScalarLam bs $ deAnnotate body) + `orElseV` vectLam True fvs bs body + where + (bs,body) = collectAnnValBinders e +-} --- ---------------------------------------------------------------------------- --- PA dictionaries +vectExpr e = cantVectorise "Can't vectorise expression" (ppr $ deAnnotate e) -paArgType :: Type -> Kind -> VM (Maybe Type) -paArgType ty k - | Just k' <- kindView k = paArgType ty k' +vectFnExpr :: Bool -> Bool -> CoreExprWithFVs -> VM (Inline, VExpr) +vectFnExpr inline loop_breaker e@(fvs, AnnLam bndr _) + | isId bndr = onlyIfV (isEmptyVarSet fvs) + (mark DontInline . vectScalarLam bs $ deAnnotate body) + `orElseV` mark inlineMe (vectLam inline loop_breaker fvs bs body) + where + (bs,body) = collectAnnValBinders e +vectFnExpr _ _ e = mark DontInline $ vectExpr e --- Here, we assume that for a kind (k1 -> k2) to be valid, k1 and k2 can only --- be made up of * and (->), i.e., they can't be coercion kinds or #. -paArgType ty (FunTy k1 k2) - = do - tv <- newTyVar FSLIT("a") k1 - ty1 <- paArgType' (TyVarTy tv) k1 - ty2 <- paArgType' (AppTy ty (TyVarTy tv)) k2 - return . Just $ ForAllTy tv (FunTy ty1 ty2) +mark :: Inline -> VM a -> VM (Inline, a) +mark b p = do { x <- p; return (b,x) } -paArgType ty k - | isLiftedTypeKind k +vectScalarLam :: [Var] -> CoreExpr -> VM VExpr +vectScalarLam args body = do - tc <- builtin paDictTyCon - return . Just $ TyConApp tc [ty] + scalars <- globalScalars + onlyIfV (all is_scalar_ty arg_tys + && is_scalar_ty res_ty + && is_scalar (extendVarSetList scalars args) body) + $ do + fn_var <- hoistExpr (fsLit "fn") (mkLams args body) DontInline + zipf <- zipScalars arg_tys res_ty + clo <- scalarClosure arg_tys res_ty (Var fn_var) + (zipf `App` Var fn_var) + clo_var <- hoistExpr (fsLit "clo") clo DontInline + lclo <- liftPD (Var clo_var) + return (Var clo_var, lclo) + where + arg_tys = map idType args + res_ty = exprType body - | otherwise - = return Nothing + is_scalar_ty ty | Just (tycon, []) <- splitTyConApp_maybe ty + = tycon == intTyCon + || tycon == floatTyCon + || tycon == doubleTyCon -paArgType' :: Type -> Kind -> VM Type -paArgType' ty k - = do - r <- paArgType ty k - case r of - Just ty' -> return ty' - Nothing -> pprPanic "paArgType'" (ppr ty) + | otherwise = False -paOfTyCon :: TyCon -> VM CoreExpr --- FIXME: just for now -paOfTyCon tc = maybeV (readGEnv $ \env -> lookupNameEnv (global_tycon_pa env) (tyConName tc)) + is_scalar vs (Var v) = v `elemVarSet` vs + is_scalar _ e@(Lit _) = is_scalar_ty $ exprType e + is_scalar vs (App e1 e2) = is_scalar vs e1 && is_scalar vs e2 + is_scalar _ _ = False -paOfType :: Type -> VM CoreExpr -paOfType ty | Just ty' <- coreView ty = paOfType ty' +vectLam :: Bool -> Bool -> VarSet -> [Var] -> CoreExprWithFVs -> VM VExpr +vectLam inline loop_breaker fvs bs body + = do + tyvars <- localTyVars + (vs, vvs) <- readLEnv $ \env -> + unzip [(var, vv) | var <- varSetElems fvs + , Just vv <- [lookupVarEnv (local_vars env) var]] + + arg_tys <- mapM (vectType . idType) bs + res_ty <- vectType (exprType $ deAnnotate body) + + buildClosures tyvars vvs arg_tys res_ty + . hoistPolyVExpr tyvars (maybe_inline (length vs + length bs)) + $ do + lc <- builtin liftingContext + (vbndrs, vbody) <- vectBndrsIn (vs ++ bs) + (vectExpr body) + vbody' <- break_loop lc res_ty vbody + return $ vLams lc vbndrs vbody' + where + maybe_inline n | inline = Inline n + | otherwise = DontInline + + break_loop lc ty (ve, le) + | loop_breaker + = do + empty <- emptyPD ty + lty <- mkPDataType ty + return (ve, mkWildCase (Var lc) intPrimTy lty + [(DEFAULT, [], le), + (LitAlt (mkMachInt 0), [], empty)]) + + | otherwise = return (ve, le) + + +vectTyAppExpr :: CoreExprWithFVs -> [Type] -> VM VExpr +vectTyAppExpr (_, AnnVar v) tys = vectPolyVar v tys +vectTyAppExpr e tys = cantVectorise "Can't vectorise expression" + (ppr $ deAnnotate e `mkTyApps` tys) + +-- We convert +-- +-- case e :: t of v { ... } +-- +-- to +-- +-- V: let v' = e in case v' of _ { ... } +-- L: let v' = e in case v' `cast` ... of _ { ... } +-- +-- When lifting, we have to do it this way because v must have the type +-- [:V(T):] but the scrutinee must be cast to the representation type. We also +-- have to handle the case where v is a wild var correctly. +-- + +-- FIXME: this is too lazy +vectAlgCase :: TyCon -> [Type] -> CoreExprWithFVs -> Var -> Type + -> [(AltCon, [Var], CoreExprWithFVs)] + -> VM VExpr +vectAlgCase _tycon _ty_args scrut bndr ty [(DEFAULT, [], body)] + = do + vscrut <- vectExpr scrut + (vty, lty) <- vectAndLiftType ty + (vbndr, vbody) <- vectBndrIn bndr (vectExpr body) + return $ vCaseDEFAULT vscrut vbndr vty lty vbody -paOfType (TyVarTy tv) = maybeV (readLEnv $ \env -> lookupVarEnv (local_tyvar_pa env) tv) -paOfType (AppTy ty1 ty2) +vectAlgCase _tycon _ty_args scrut bndr ty [(DataAlt _, [], body)] = do - e1 <- paOfType ty1 - e2 <- paOfType ty2 - return $ mkApps e1 [Type ty2, e2] -paOfType (TyConApp tc tys) + vscrut <- vectExpr scrut + (vty, lty) <- vectAndLiftType ty + (vbndr, vbody) <- vectBndrIn bndr (vectExpr body) + return $ vCaseDEFAULT vscrut vbndr vty lty vbody + +vectAlgCase _tycon _ty_args scrut bndr ty [(DataAlt dc, bndrs, body)] = do - e <- paOfTyCon tc - es <- mapM paOfType tys - return $ mkApps e [arg | (t,e) <- zip tys es, arg <- [Type t, e]] -paOfType (FunTy ty1 ty2) = paOfType (TyConApp funTyCon [ty1,ty2]) -paOfType t@(ForAllTy tv ty) = pprPanic "paOfType:" (ppr t) -paOfType ty = pprPanic "paOfType:" (ppr ty) - + (vty, lty) <- vectAndLiftType ty + vexpr <- vectExpr scrut + (vbndr, (vbndrs, (vect_body, lift_body))) + <- vect_scrut_bndr + . vectBndrsIn bndrs + $ vectExpr body + let (vect_bndrs, lift_bndrs) = unzip vbndrs + (vscrut, lscrut, pdata_tc, _arg_tys) <- mkVScrut (vVar vbndr) + vect_dc <- maybeV (lookupDataCon dc) + let [pdata_dc] = tyConDataCons pdata_tc + + let vcase = mk_wild_case vscrut vty vect_dc vect_bndrs vect_body + lcase = mk_wild_case lscrut lty pdata_dc lift_bndrs lift_body + + return $ vLet (vNonRec vbndr vexpr) (vcase, lcase) + where + vect_scrut_bndr | isDeadBinder bndr = vectBndrNewIn bndr (fsLit "scrut") + | otherwise = vectBndrIn bndr + mk_wild_case expr ty dc bndrs body + = mkWildCase expr (exprType expr) ty [(DataAlt dc, bndrs, body)] --- ---------------------------------------------------------------------------- --- Types - -vectTyCon :: TyCon -> VM TyCon -vectTyCon tc - | isFunTyCon tc = builtin closureTyCon - | isBoxedTupleTyCon tc = return tc - | isUnLiftedTyCon tc = return tc - | otherwise = do - r <- lookupTyCon tc - case r of - Just tc' -> return tc' - - -- FIXME: just for now - Nothing -> pprTrace "ccTyCon:" (ppr tc) $ return tc - -vectType :: Type -> VM Type -vectType ty | Just ty' <- coreView ty = vectType ty -vectType (TyVarTy tv) = return $ TyVarTy tv -vectType (AppTy ty1 ty2) = liftM2 AppTy (vectType ty1) (vectType ty2) -vectType (TyConApp tc tys) = liftM2 TyConApp (vectTyCon tc) (mapM vectType tys) -vectType (FunTy ty1 ty2) = liftM2 TyConApp (builtin closureTyCon) - (mapM vectType [ty1,ty2]) -vectType (ForAllTy tv ty) +vectAlgCase tycon _ty_args scrut bndr ty alts = do - r <- paArgType (TyVarTy tv) (tyVarKind tv) - ty' <- vectType ty - return . ForAllTy tv $ case r of { Just paty -> FunTy paty ty'; Nothing -> ty' } + vect_tc <- maybeV (lookupTyCon tycon) + (vty, lty) <- vectAndLiftType ty -vectType ty = pprPanic "vectType:" (ppr ty) + let arity = length (tyConDataCons vect_tc) + sel_ty <- builtin (selTy arity) + sel_bndr <- newLocalVar (fsLit "sel") sel_ty + let sel = Var sel_bndr -isClosureTyCon :: TyCon -> Bool -isClosureTyCon tc = tyConUnique tc == closureTyConKey + (vbndr, valts) <- vect_scrut_bndr + $ mapM (proc_alt arity sel vty lty) alts' + let (vect_dcs, vect_bndrss, lift_bndrss, vbodies) = unzip4 valts -splitClosureTy :: Type -> (Type, Type) -splitClosureTy ty - | Just (tc, [arg_ty, res_ty]) <- splitTyConApp_maybe ty - , isClosureTyCon tc - = (arg_ty, res_ty) + vexpr <- vectExpr scrut + (vect_scrut, lift_scrut, pdata_tc, _arg_tys) <- mkVScrut (vVar vbndr) + let [pdata_dc] = tyConDataCons pdata_tc - | otherwise = pprPanic "splitClosureTy" (ppr ty) + let (vect_bodies, lift_bodies) = unzip vbodies -mkPArrayTy :: Type -> VM Type -mkPArrayTy ty = do - tc <- builtin parrayTyCon - return $ TyConApp tc [ty] + vdummy <- newDummyVar (exprType vect_scrut) + ldummy <- newDummyVar (exprType lift_scrut) + let vect_case = Case vect_scrut vdummy vty + (zipWith3 mk_vect_alt vect_dcs vect_bndrss vect_bodies) + + lc <- builtin liftingContext + lbody <- combinePD vty (Var lc) sel lift_bodies + let lift_case = Case lift_scrut ldummy lty + [(DataAlt pdata_dc, sel_bndr : concat lift_bndrss, + lbody)] + + return . vLet (vNonRec vbndr vexpr) + $ (vect_case, lift_case) + where + vect_scrut_bndr | isDeadBinder bndr = vectBndrNewIn bndr (fsLit "scrut") + | otherwise = vectBndrIn bndr + + alts' = sortBy (\(alt1, _, _) (alt2, _, _) -> cmp alt1 alt2) alts + + cmp (DataAlt dc1) (DataAlt dc2) = dataConTag dc1 `compare` dataConTag dc2 + cmp DEFAULT DEFAULT = EQ + cmp DEFAULT _ = LT + cmp _ DEFAULT = GT + cmp _ _ = panic "vectAlgCase/cmp" + + proc_alt arity sel _ lty (DataAlt dc, bndrs, body) + = do + vect_dc <- maybeV (lookupDataCon dc) + let ntag = dataConTagZ vect_dc + tag = mkDataConTag vect_dc + fvs = freeVarsOf body `delVarSetList` bndrs + + sel_tags <- liftM (`App` sel) (builtin (selTags arity)) + lc <- builtin liftingContext + elems <- builtin (selElements arity ntag) + + (vbndrs, vbody) + <- vectBndrsIn bndrs + . localV + $ do + binds <- mapM (pack_var (Var lc) sel_tags tag) + . filter isLocalId + $ varSetElems fvs + (ve, le) <- vectExpr body + return (ve, Case (elems `App` sel) lc lty + [(DEFAULT, [], (mkLets (concat binds) le))]) + -- empty <- emptyPD vty + -- return (ve, Case (elems `App` sel) lc lty + -- [(DEFAULT, [], Let (NonRec flags_var flags_expr) + -- $ mkLets (concat binds) le), + -- (LitAlt (mkMachInt 0), [], empty)]) + let (vect_bndrs, lift_bndrs) = unzip vbndrs + return (vect_dc, vect_bndrs, lift_bndrs, vbody) + + proc_alt _ _ _ _ _ = panic "vectAlgCase/proc_alt" + + mk_vect_alt vect_dc bndrs body = (DataAlt vect_dc, bndrs, body) + + pack_var len tags t v + = do + r <- lookupVar v + case r of + Local (vv, lv) -> + do + lv' <- cloneVar lv + expr <- packByTagPD (idType vv) (Var lv) len tags t + updLEnv (\env -> env { local_vars = extendVarEnv + (local_vars env) v (vv, lv') }) + return [(NonRec lv' expr)] + + _ -> return []