X-Git-Url: http://git.megacz.com/?p=ghc-hetmet.git;a=blobdiff_plain;f=compiler%2Fvectorise%2FVectorise.hs;h=cd1f42945474f6b39a4352036519cea14f4532cc;hp=a35c8066f9e5d081fc5d3ddce01655cbc1d41795;hb=9bcd95bad83ee937c178970e8b729732e680fe1e;hpb=76fb33900748c86d97aa528bae91cd1844aed97d diff --git a/compiler/vectorise/Vectorise.hs b/compiler/vectorise/Vectorise.hs index a35c806..cd1f429 100644 --- a/compiler/vectorise/Vectorise.hs +++ b/compiler/vectorise/Vectorise.hs @@ -1,75 +1,66 @@ + 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 CoreFVs -import SimplMonad ( SimplCount, zeroSimplCount ) -import Rules ( RuleBase ) +import CoreMonad ( CoreM, getHscEnv, liftIO ) import DataCon import TyCon import Type import FamInstEnv ( extendFamInstEnvList ) -import InstEnv ( extendInstEnvList ) import Var import VarEnv import VarSet -import Name ( mkSysTvName, getName ) -import NameEnv import Id -import MkId ( unwrapFamInstScrut ) import OccName -import DsMonad hiding (mapAndUnzipM) -import DsUtils ( mkCoreTup, mkCoreTupTy ) +import DsMonad -import PrelNames +import Literal ( Literal, mkMachInt ) import TysWiredIn -import TysPrim ( intPrimTy ) -import BasicTypes ( Boxity(..) ) import Outputable import FastString -import Control.Monad ( liftM, liftM2, mapAndUnzipM ) +import Control.Monad ( liftM, liftM2, zipWithM ) +import Data.List ( sortBy, unzip4 ) -vectorise :: HscEnv -> UniqSupply -> RuleBase -> ModGuts - -> IO (SimplCount, ModGuts) -vectorise hsc_env _ _ guts +vectorise :: PackageId -> ModGuts -> CoreM ModGuts +vectorise backend guts = do + hsc_env <- getHscEnv + liftIO $ vectoriseIO backend hsc_env guts + +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 (zeroSimplCount dflags, 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 = do - (types', fam_insts, insts) <- vectTypeEnv (mg_types guts) + (types', fam_insts, tc_binds) <- vectTypeEnv (mg_types guts) let fam_inst_env' = extendFamInstEnvList (mg_fam_inst_env guts) fam_insts - inst_env' = extendInstEnvList (mg_inst_env guts) insts - updGEnv (setInstEnvs inst_env' fam_inst_env') - - binds' <- mapM vectTopBind (mg_binds guts) + 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 = binds' - , mg_inst_env = inst_env' + , mg_binds = Rec tc_binds : binds' , mg_fam_inst_env = fam_inst_env' - , mg_insts = mg_insts guts ++ insts , mg_fam_insts = mg_fam_insts guts ++ fam_insts } @@ -77,18 +68,20 @@ vectTopBind :: CoreBind -> VM CoreBind vectTopBind b@(NonRec var expr) = do var' <- vectTopBinder var - expr' <- vectTopRhs expr + expr' <- vectTopRhs var expr hs <- takeHoisted - return . Rec $ (var, expr) : (var', expr') : hs + cexpr <- tryConvert var var' expr + return . Rec $ (var, cexpr) : (var', expr') : hs `orElseV` return b vectTopBind b@(Rec bs) = do vars' <- mapM vectTopBinder vars - exprs' <- mapM vectTopRhs exprs + exprs' <- zipWithM vectTopRhs vars exprs hs <- takeHoisted - return . Rec $ bs ++ zip vars' exprs' ++ hs + cexprs <- sequence $ zipWith3 tryConvert vars vars' exprs + return . Rec $ zip vars cexprs ++ zip vars' exprs' ++ hs `orElseV` return b where @@ -97,310 +90,373 @@ vectTopBind b@(Rec bs) vectTopBinder :: Var -> VM Var vectTopBinder var = do - vty <- vectType (idType var) - name <- cloneName mkVectOcc (getName var) - let var' | isExportedId var = Id.mkExportedLocalId name vty - | otherwise = Id.mkLocalId name vty + vty <- vectType (idType var) + var' <- cloneId mkVectOcc var vty defGlobalVar var var' return var' - -vectTopRhs :: CoreExpr -> VM CoreExpr -vectTopRhs = liftM fst . closedV . vectPolyExpr (panic "Empty lifting context") . freeVars + +vectTopRhs :: Var -> CoreExpr -> VM CoreExpr +vectTopRhs var expr + = do + closedV . liftM vectorised + . inBind var + $ vectPolyExpr (freeVars expr) + +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 <- mkPArrayType 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) } + +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 (Var, Var, a) +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) + +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 ([Var], [Var], a) +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 -capply :: (CoreExpr, CoreExpr) -> (CoreExpr, CoreExpr) -> VM (CoreExpr, CoreExpr) -capply (vfn, lfn) (varg, larg) - = 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]) - where - fn_ty = exprType vfn - (arg_ty, res_ty) = splitClosureTy fn_ty - -vectVar :: CoreExpr -> Var -> VM (CoreExpr, CoreExpr) -vectVar lc v +vectVar :: Var -> VM VExpr +vectVar v = do r <- lookupVar v case r of - Local es -> return es - Global vexpr -> do - lexpr <- replicatePA vexpr lc - return (vexpr, lexpr) - -vectPolyVar :: CoreExpr -> Var -> [Type] -> VM (CoreExpr, CoreExpr) -vectPolyVar lc v tys + Local (vv,lv) -> return (Var vv, Var lv) + Global vv -> do + let vexpr = Var vv + lexpr <- liftPA vexpr + return (vexpr, lexpr) + +vectPolyVar :: Var -> [Type] -> VM VExpr +vectPolyVar v tys = do + vtys <- mapM vectType tys r <- lookupVar v case r of - Local (vexpr, lexpr) -> liftM2 (,) (mk_app vexpr) (mk_app lexpr) - Global poly -> do - vexpr <- mk_app poly - lexpr <- replicatePA vexpr lc - return (vexpr, lexpr) - where - mk_app e = applyToTypes e =<< mapM vectType tys - -vectPolyExpr :: CoreExpr -> CoreExprWithFVs -> VM (CoreExpr, CoreExpr) -vectPolyExpr lc expr - = localV - . abstractOverTyVars tvs $ \mk_lams -> - -- FIXME: shadowing (tvs in lc) + Local (vv, lv) -> liftM2 (,) (polyApply (Var vv) vtys) + (polyApply (Var lv) vtys) + Global poly -> do + vexpr <- polyApply (Var poly) vtys + lexpr <- liftPA vexpr + return (vexpr, lexpr) + +vectLiteral :: Literal -> VM VExpr +vectLiteral lit + = do + lexpr <- liftPA (Lit lit) + return (Lit lit, lexpr) + +vectPolyExpr :: CoreExprWithFVs -> VM VExpr +vectPolyExpr (_, AnnNote note expr) + = liftM (vNote note) $ vectPolyExpr expr +vectPolyExpr expr + = polyAbstract tvs $ \abstract -> do - (vmono, lmono) <- vectExpr lc mono - return $ (mk_lams vmono, mk_lams lmono) + mono' <- vectExpr mono + return $ mapVect abstract mono' where - (tvs, mono) = collectAnnTypeBinders expr - -vectExpr :: CoreExpr -> CoreExprWithFVs -> VM (CoreExpr, CoreExpr) -vectExpr lc (_, AnnType ty) - = do - vty <- vectType ty - return (Type vty, Type vty) + (tvs, mono) = collectAnnTypeBinders expr -vectExpr lc (_, AnnVar v) = vectVar lc v +vectExpr :: CoreExprWithFVs -> VM VExpr +vectExpr (_, AnnType ty) + = liftM vType (vectType ty) -vectExpr lc (_, AnnLit lit) - = do - let vexpr = Lit lit - lexpr <- replicatePA vexpr lc - return (vexpr, lexpr) +vectExpr (_, AnnVar v) = vectVar v -vectExpr lc (_, AnnNote note expr) - = do - (vexpr, lexpr) <- vectExpr lc expr - return (Note note vexpr, Note note lexpr) +vectExpr (_, AnnLit lit) = vectLiteral lit -vectExpr lc e@(_, AnnApp _ arg) +vectExpr (_, AnnNote note expr) + = liftM (vNote note) (vectExpr expr) + +vectExpr e@(_, AnnApp _ arg) | isAnnTypeArg arg - = vectTyAppExpr lc fn tys + = vectTyAppExpr fn tys where (fn, tys) = collectAnnTypeArgs e -vectExpr lc (_, AnnApp fn arg) +vectExpr (_, AnnApp (_, AnnVar v) (_, AnnLit lit)) + | Just con <- isDataConId_maybe v + , is_special_con con = do - fn' <- vectExpr lc fn - arg' <- vectExpr lc arg - capply fn' arg' - -vectExpr lc (_, AnnCase expr bndr ty alts) - = panic "vectExpr: case" + let vexpr = App (Var v) (Lit lit) + lexpr <- liftPA vexpr + return (vexpr, lexpr) + where + is_special_con con = con `elem` [intDataCon, floatDataCon, doubleDataCon] -vectExpr lc (_, AnnLet (AnnNonRec bndr rhs) body) - = do - (vrhs, lrhs) <- vectPolyExpr 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) +vectExpr (_, AnnApp fn arg) = do - (vbndrs, lbndrs, (vrhss, vbody, lrhss, lbody)) <- vectBndrsIn bndrs vect - return (Let (Rec (zip vbndrs vrhss)) vbody, - Let (Rec (zip lbndrs lrhss)) lbody) + arg_ty' <- vectType arg_ty + res_ty' <- vectType res_ty + fn' <- vectExpr fn + arg' <- vectExpr arg + mkClosureApp arg_ty' res_ty' fn' arg' where - (bndrs, rhss) = unzip prs - - vect = do - (vrhss, lrhss) <- mapAndUnzipM (vectExpr lc) rhss - (vbody, lbody) <- vectPolyExpr lc body - return (vrhss, vbody, lrhss, lbody) + (arg_ty, res_ty) = splitFunTy . exprType $ deAnnotate fn -vectExpr lc e@(_, AnnLam bndr body) - | isTyVar bndr = pprPanic "vectExpr" (ppr $ deAnnotate e) +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 lc (fvs, AnnLam bndr body) +vectExpr (_, AnnLet (AnnNonRec bndr rhs) body) = do - tyvars <- localTyVars - info <- mkCEnvInfo fvs bndr body - (poly_vfn, poly_lfn) <- mkClosureFns info tyvars bndr body - - vfn_var <- hoistExpr FSLIT("vfn") poly_vfn - lfn_var <- hoistExpr FSLIT("lfn") poly_lfn - - let (venv, lenv) = mkClosureEnvs info lc - - let env_ty = cenv_vty info - - pa_dict <- paDictOfType env_ty + vrhs <- localV . inBind bndr $ vectPolyExpr rhs + (vbndr, vbody) <- vectBndrIn bndr (vectExpr body) + return $ vLet (vNonRec vbndr vrhs) vbody - arg_ty <- vectType (varType bndr) - res_ty <- vectType (exprType $ deAnnotate body) - - -- FIXME: move the functions to the top level - mono_vfn <- applyToTypes (Var vfn_var) (mkTyVarTys tyvars) - mono_lfn <- applyToTypes (Var lfn_var) (mkTyVarTys tyvars) - - mk_clo <- builtin mkClosureVar - mk_cloP <- builtin mkClosurePVar - - let vclo = Var mk_clo `mkTyApps` [arg_ty, res_ty, env_ty] - `mkApps` [pa_dict, mono_vfn, mono_lfn, venv] - - lclo = Var mk_cloP `mkTyApps` [arg_ty, res_ty, env_ty] - `mkApps` [pa_dict, mono_vfn, mono_lfn, lenv] - - return (vclo, lclo) - - -data CEnvInfo = CEnvInfo { - cenv_vars :: [Var] - , cenv_values :: [(CoreExpr, CoreExpr)] - , cenv_vty :: Type - , cenv_lty :: Type - , cenv_repr_tycon :: TyCon - , cenv_repr_tyargs :: [Type] - , cenv_repr_datacon :: DataCon - } - -mkCEnvInfo :: VarSet -> Var -> CoreExprWithFVs -> VM CEnvInfo -mkCEnvInfo fvs arg body +vectExpr (_, AnnLet (AnnRec bs) body) = do - locals <- readLEnv local_vars - let - (vars, vals) = unzip - [(var, val) | var <- varSetElems fvs - , Just val <- [lookupVarEnv locals var]] - vtys <- mapM (vectType . varType) vars - - (vty, repr_tycon, repr_tyargs, repr_datacon) <- mk_env_ty vtys - lty <- mkPArrayType vty - - return $ CEnvInfo { - cenv_vars = vars - , cenv_values = vals - , cenv_vty = vty - , cenv_lty = lty - , cenv_repr_tycon = repr_tycon - , cenv_repr_tyargs = repr_tyargs - , cenv_repr_datacon = repr_datacon - } + (vbndrs, (vrhss, vbody)) <- vectBndrsIn bndrs + $ liftM2 (,) + (zipWithM vect_rhs bndrs rhss) + (vectPolyExpr body) + return $ vLet (vRec vbndrs vrhss) vbody where - mk_env_ty [vty] - = return (vty, error "absent cinfo_repr_tycon" - , error "absent cinfo_repr_tyargs" - , error "absent cinfo_repr_datacon") - - mk_env_ty vtys - = do - let ty = mkCoreTupTy vtys - (repr_tc, repr_tyargs) <- lookupPArrayFamInst ty - let [repr_con] = tyConDataCons repr_tc - return (ty, repr_tc, repr_tyargs, repr_con) + (bndrs, rhss) = unzip bs - + vect_rhs bndr rhs = localV + . inBind bndr + $ vectExpr rhs -mkClosureEnvs :: CEnvInfo -> CoreExpr -> (CoreExpr, CoreExpr) -mkClosureEnvs info lc - | [] <- vals - = (Var unitDataConId, mkApps (Var $ dataConWrapId (cenv_repr_datacon info)) - [lc, Var unitDataConId]) +vectExpr e@(fvs, AnnLam bndr _) + | isId bndr = vectLam fvs bs body + where + (bs,body) = collectAnnValBinders e - | [(vval, lval)] <- vals - = (vval, lval) +vectExpr e = cantVectorise "Can't vectorise expression" (ppr $ deAnnotate e) - | otherwise - = (mkCoreTup vvals, Var (dataConWrapId $ cenv_repr_datacon info) - `mkTyApps` cenv_repr_tyargs info - `mkApps` (lc : lvals)) +vectLam :: VarSet -> [Var] -> CoreExprWithFVs -> VM VExpr +vectLam 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 + $ do + lc <- builtin liftingContext + (vbndrs, vbody) <- vectBndrsIn (vs ++ bs) + (vectExpr body) + return $ vLams lc vbndrs vbody + +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 - where - vals = cenv_values info - (vvals, lvals) = unzip vals - -mkClosureFns :: CEnvInfo -> [TyVar] -> Var -> CoreExprWithFVs - -> VM (CoreExpr, CoreExpr) -mkClosureFns info tyvars arg body - = closedV - . abstractOverTyVars tyvars - $ \mk_tlams -> - do - (vfn, lfn) <- mkClosureMonoFns info arg body - return (mk_tlams vfn, mk_tlams lfn) - -mkClosureMonoFns :: CEnvInfo -> Var -> CoreExprWithFVs -> VM (CoreExpr, CoreExpr) -mkClosureMonoFns info arg body +vectAlgCase _tycon _ty_args scrut bndr ty [(DataAlt _, [], body)] = do - lc_bndr <- newLocalVar FSLIT("lc") intPrimTy - (varg : vbndrs, larg : lbndrs, (vbody, lbody)) - <- vectBndrsIn (arg : cenv_vars info) - (vectExpr (Var lc_bndr) body) + vscrut <- vectExpr scrut + (vty, lty) <- vectAndLiftType ty + (vbndr, vbody) <- vectBndrIn bndr (vectExpr body) + return $ vCaseDEFAULT vscrut vbndr vty lty vbody - venv_bndr <- newLocalVar FSLIT("env") vty - lenv_bndr <- newLocalVar FSLIT("env") lty +vectAlgCase tycon _ty_args scrut bndr ty [(DataAlt dc, bndrs, body)] + = do + vect_tc <- maybeV (lookupTyCon tycon) + (vty, lty) <- vectAndLiftType ty + vexpr <- vectExpr scrut + (vbndr, (vbndrs, vbody)) <- vect_scrut_bndr + . vectBndrsIn bndrs + $ vectExpr body + + (vscrut, arr_tc, _arg_tys) <- mkVScrut (vVar vbndr) + vect_dc <- maybeV (lookupDataCon dc) + let [arr_dc] = tyConDataCons arr_tc + repr <- mkRepr vect_tc + shape_bndrs <- arrShapeVars repr + return . vLet (vNonRec vbndr vexpr) + $ vCaseProd vscrut vty lty vect_dc arr_dc shape_bndrs vbndrs vbody + where + vect_scrut_bndr | isDeadBinder bndr = vectBndrNewIn bndr (fsLit "scrut") + | otherwise = vectBndrIn bndr - let vcase = bind_venv (Var venv_bndr) vbody vbndrs - lcase <- bind_lenv (Var lenv_bndr) lbody lc_bndr lbndrs - return (mkLams [venv_bndr, varg] vcase, mkLams [lenv_bndr, larg] lcase) +vectAlgCase tycon _ty_args scrut bndr ty alts + = do + vect_tc <- maybeV (lookupTyCon tycon) + (vty, lty) <- vectAndLiftType ty + repr <- mkRepr vect_tc + shape_bndrs <- arrShapeVars repr + (len, sel, indices) <- arrSelector repr (map Var shape_bndrs) + + (vbndr, valts) <- vect_scrut_bndr $ mapM (proc_alt sel vty lty) alts' + let (vect_dcs, vect_bndrss, lift_bndrss, vbodies) = unzip4 valts + + vexpr <- vectExpr scrut + (vscrut, arr_tc, _arg_tys) <- mkVScrut (vVar vbndr) + let [arr_dc] = tyConDataCons arr_tc + + let (vect_scrut, lift_scrut) = vscrut + (vect_bodies, lift_bodies) = unzip vbodies + + 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) + + lbody <- combinePA vty len sel indices lift_bodies + let lift_case = Case lift_scrut ldummy lty + [(DataAlt arr_dc, shape_bndrs ++ concat lift_bndrss, + lbody)] + + return . vLet (vNonRec vbndr vexpr) + $ (vect_case, lift_case) where - vty = cenv_vty info - lty = cenv_lty info + vect_scrut_bndr | isDeadBinder bndr = vectBndrNewIn bndr (fsLit "scrut") + | otherwise = vectBndrIn bndr - arity = length (cenv_vars info) + alts' = sortBy (\(alt1, _, _) (alt2, _, _) -> cmp alt1 alt2) alts - bind_venv venv vbody [] = vbody - bind_venv venv vbody [vbndr] = Let (NonRec vbndr venv) vbody - bind_venv venv vbody vbndrs - = Case venv (mkWildId vty) (exprType vbody) - [(DataAlt (tupleCon Boxed arity), vbndrs, vbody)] + cmp (DataAlt dc1) (DataAlt dc2) = dataConTag dc1 `compare` dataConTag dc2 + cmp DEFAULT DEFAULT = EQ + cmp DEFAULT _ = LT + cmp _ DEFAULT = GT + cmp _ _ = panic "vectAlgCase/cmp" - bind_lenv lenv lbody lc_bndr [lbndr] + proc_alt sel vty lty (DataAlt dc, bndrs, body) + = do + vect_dc <- maybeV (lookupDataCon dc) + let tag = mkDataConTag vect_dc + fvs = freeVarsOf body `delVarSetList` bndrs + (vect_bndrs, lift_bndrs, vbody) + <- vect_alt_bndrs bndrs + $ \len -> packLiftingContext len sel tag fvs vty lty + $ vectExpr body + + return (vect_dc, vect_bndrs, lift_bndrs, vbody) + proc_alt _ _ _ _ = panic "vectAlgCase/proc_alt" + + vect_alt_bndrs [] p = do - len <- lengthPA (Var lbndr) - return . Let (NonRec lbndr lenv) - $ Case len - lc_bndr - (exprType lbody) - [(DEFAULT, [], lbody)] - - bind_lenv lenv lbody lc_bndr lbndrs - = let scrut = unwrapFamInstScrut (cenv_repr_tycon info) - (cenv_repr_tyargs info) - lenv - lbndrs' | null lbndrs = [mkWildId unitTy] - | otherwise = lbndrs - in - return - $ Case scrut - (mkWildId (exprType scrut)) - (exprType lbody) - [(DataAlt (cenv_repr_datacon info), lc_bndr : lbndrs', lbody)] - -vectTyAppExpr :: CoreExpr -> CoreExprWithFVs -> [Type] -> VM (CoreExpr, CoreExpr) -vectTyAppExpr lc (_, AnnVar v) tys = vectPolyVar lc v tys -vectTyAppExpr lc e tys = pprPanic "vectTyAppExpr" (ppr $ deAnnotate e) + void_tc <- builtin voidTyCon + let void_ty = mkTyConApp void_tc [] + arr_ty <- mkPArrayType void_ty + bndr <- newLocalVar (fsLit "voids") arr_ty + len <- lengthPA void_ty (Var bndr) + e <- p len + return ([], [bndr], e) + + vect_alt_bndrs bndrs p + = localV + $ do + vbndrs <- mapM vectBndr bndrs + let (vect_bndrs, lift_bndrs) = unzip vbndrs + vv : _ = vect_bndrs + lv : _ = lift_bndrs + len <- lengthPA (idType vv) (Var lv) + e <- p len + return (vect_bndrs, lift_bndrs, e) + + mk_vect_alt vect_dc bndrs body = (DataAlt vect_dc, bndrs, body) + +packLiftingContext :: CoreExpr -> CoreExpr -> CoreExpr -> VarSet + -> Type -> Type -> VM VExpr -> VM VExpr +packLiftingContext len shape tag fvs vty lty p + = do + select <- builtin selectPAIntPrimVar + let sel_expr = mkApps (Var select) [shape, tag] + sel_var <- newLocalVar (fsLit "sel#") (exprType sel_expr) + lc_var <- builtin liftingContext + localV $ + do + bnds <- mapM (packFreeVar (Var lc_var) (Var sel_var)) + . filter isLocalId + $ varSetElems fvs + (vexpr, lexpr) <- p + empty <- emptyPA vty + return (vexpr, Let (NonRec sel_var sel_expr) + $ Case len lc_var lty + [(DEFAULT, [], mkLets (concat bnds) lexpr), + (LitAlt (mkMachInt 0), [], empty)]) + +packFreeVar :: CoreExpr -> CoreExpr -> Var -> VM [CoreBind] +packFreeVar len sel v + = do + r <- lookupVar v + case r of + Local (vv,lv) -> + do + lv' <- cloneVar lv + expr <- packPA (idType vv) (Var lv) len sel + updLEnv (upd vv lv') + return [(NonRec lv' expr)] + + _ -> return [] + where + upd vv lv' env = env { local_vars = extendVarEnv (local_vars env) v (vv, lv') }