summaryrefslogtreecommitdiff
path: root/compiler/vectorise/Vectorise/Generic/PAMethods.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/vectorise/Vectorise/Generic/PAMethods.hs')
-rw-r--r--compiler/vectorise/Vectorise/Generic/PAMethods.hs584
1 files changed, 0 insertions, 584 deletions
diff --git a/compiler/vectorise/Vectorise/Generic/PAMethods.hs b/compiler/vectorise/Vectorise/Generic/PAMethods.hs
deleted file mode 100644
index d480ea926b..0000000000
--- a/compiler/vectorise/Vectorise/Generic/PAMethods.hs
+++ /dev/null
@@ -1,584 +0,0 @@
-
--- | Generate methods for the PA class.
---
--- TODO: there is a large amount of redundancy here between the
--- a, PData a, and PDatas a forms. See if we can factor some of this out.
---
-module Vectorise.Generic.PAMethods
- ( buildPReprTyCon
- , buildPAScAndMethods
- ) where
-
-import Vectorise.Utils
-import Vectorise.Monad
-import Vectorise.Builtins
-import Vectorise.Generic.Description
-import CoreSyn
-import CoreUtils
-import FamInstEnv
-import MkCore ( mkWildCase, mkCoreLet )
-import TyCon
-import CoAxiom
-import Type
-import OccName
-import Coercion
-import MkId
-import FamInst
-import TysPrim( intPrimTy )
-
-import DynFlags
-import FastString
-import MonadUtils
-import Control.Monad
-import Outputable
-
-
-buildPReprTyCon :: TyCon -> TyCon -> SumRepr -> VM FamInst
-buildPReprTyCon orig_tc vect_tc repr
- = do name <- mkLocalisedName mkPReprTyConOcc (tyConName orig_tc)
- rhs_ty <- sumReprType repr
- prepr_tc <- builtin preprTyCon
- let axiom = mkSingleCoAxiom Nominal name tyvars [] prepr_tc instTys rhs_ty
- liftDs $ newFamInst SynFamilyInst axiom
- where
- tyvars = tyConTyVars vect_tc
- instTys = [mkTyConApp vect_tc . mkTyVarTys $ tyConTyVars vect_tc]
-
--- buildPAScAndMethods --------------------------------------------------------
-
--- | This says how to build the PR superclass and methods of PA
--- Recall the definition of the PA class:
---
--- @
--- class class PR (PRepr a) => PA a where
--- toPRepr :: a -> PRepr a
--- fromPRepr :: PRepr a -> a
---
--- toArrPRepr :: PData a -> PData (PRepr a)
--- fromArrPRepr :: PData (PRepr a) -> PData a
---
--- toArrPReprs :: PDatas a -> PDatas (PRepr a)
--- fromArrPReprs :: PDatas (PRepr a) -> PDatas a
--- @
---
-type PAInstanceBuilder
- = TyCon -- ^ Vectorised TyCon
- -> CoAxiom Unbranched
- -- ^ Coercion to the representation TyCon
- -> TyCon -- ^ 'PData' TyCon
- -> TyCon -- ^ 'PDatas' TyCon
- -> SumRepr -- ^ Description of generic representation.
- -> VM CoreExpr -- ^ Instance function.
-
-
-buildPAScAndMethods :: VM [(String, PAInstanceBuilder)]
-buildPAScAndMethods
- = return [ ("toPRepr", buildToPRepr)
- , ("fromPRepr", buildFromPRepr)
- , ("toArrPRepr", buildToArrPRepr)
- , ("fromArrPRepr", buildFromArrPRepr)
- , ("toArrPReprs", buildToArrPReprs)
- , ("fromArrPReprs", buildFromArrPReprs)]
-
-
--- buildToPRepr ---------------------------------------------------------------
--- | Build the 'toRepr' method of the PA class.
-buildToPRepr :: PAInstanceBuilder
-buildToPRepr vect_tc repr_ax _ _ repr
- = do let arg_ty = mkTyConApp vect_tc ty_args
-
- -- Get the representation type of the argument.
- res_ty <- mkPReprType arg_ty
-
- -- Var to bind the argument
- arg <- newLocalVar (fsLit "x") arg_ty
-
- -- Build the expression to convert the argument to the generic representation.
- result <- to_sum (Var arg) arg_ty res_ty repr
-
- return $ Lam arg result
- where
- ty_args = mkTyVarTys (tyConTyVars vect_tc)
-
- wrap_repr_inst = wrapTypeUnbranchedFamInstBody repr_ax ty_args []
-
- -- CoreExp to convert the given argument to the generic representation.
- -- We start by doing a case branch on the possible data constructors.
- to_sum :: CoreExpr -> Type -> Type -> SumRepr -> VM CoreExpr
- to_sum _ _ _ EmptySum
- = do void <- builtin voidVar
- return $ wrap_repr_inst $ Var void
-
- to_sum arg arg_ty res_ty (UnarySum r)
- = do (pat, vars, body) <- con_alt r
- return $ mkWildCase arg arg_ty res_ty
- [(pat, vars, wrap_repr_inst body)]
-
- to_sum arg arg_ty res_ty (Sum { repr_sum_tc = sum_tc
- , repr_con_tys = tys
- , repr_cons = cons })
- = do alts <- mapM con_alt cons
- let alts' = [(pat, vars, wrap_repr_inst
- $ mkConApp sum_con (map Type tys ++ [body]))
- | ((pat, vars, body), sum_con)
- <- zip alts (tyConDataCons sum_tc)]
- return $ mkWildCase arg arg_ty res_ty alts'
-
- con_alt (ConRepr con r)
- = do (vars, body) <- to_prod r
- return (DataAlt con, vars, body)
-
- -- CoreExp to convert data constructor fields to the generic representation.
- to_prod :: ProdRepr -> VM ([Var], CoreExpr)
- to_prod EmptyProd
- = do void <- builtin voidVar
- return ([], Var void)
-
- to_prod (UnaryProd comp)
- = do var <- newLocalVar (fsLit "x") (compOrigType comp)
- body <- to_comp (Var var) comp
- return ([var], body)
-
- to_prod (Prod { repr_tup_tc = tup_tc
- , repr_comp_tys = tys
- , repr_comps = comps })
- = do vars <- newLocalVars (fsLit "x") (map compOrigType comps)
- exprs <- zipWithM to_comp (map Var vars) comps
- let [tup_con] = tyConDataCons tup_tc
- return (vars, mkConApp tup_con (map Type tys ++ exprs))
-
- -- CoreExp to convert a data constructor component to the generic representation.
- to_comp :: CoreExpr -> CompRepr -> VM CoreExpr
- to_comp expr (Keep _ _) = return expr
- to_comp expr (Wrap ty) = wrapNewTypeBodyOfWrap expr ty
-
-
--- buildFromPRepr -------------------------------------------------------------
-
--- |Build the 'fromPRepr' method of the PA class.
---
-buildFromPRepr :: PAInstanceBuilder
-buildFromPRepr vect_tc repr_ax _ _ repr
- = do
- arg_ty <- mkPReprType res_ty
- arg <- newLocalVar (fsLit "x") arg_ty
-
- result <- from_sum (unwrapTypeUnbranchedFamInstScrut repr_ax ty_args [] (Var arg))
- repr
- return $ Lam arg result
- where
- ty_args = mkTyVarTys (tyConTyVars vect_tc)
- res_ty = mkTyConApp vect_tc ty_args
-
- from_sum _ EmptySum
- = do dummy <- builtin fromVoidVar
- return $ Var dummy `App` Type res_ty
-
- from_sum expr (UnarySum r) = from_con expr r
- from_sum expr (Sum { repr_sum_tc = sum_tc
- , repr_con_tys = tys
- , repr_cons = cons })
- = do vars <- newLocalVars (fsLit "x") tys
- es <- zipWithM from_con (map Var vars) cons
- return $ mkWildCase expr (exprType expr) res_ty
- [(DataAlt con, [var], e)
- | (con, var, e) <- zip3 (tyConDataCons sum_tc) vars es]
-
- from_con expr (ConRepr con r)
- = from_prod expr (mkConApp con $ map Type ty_args) r
-
- from_prod _ con EmptyProd = return con
- from_prod expr con (UnaryProd r)
- = do e <- from_comp expr r
- return $ con `App` e
-
- from_prod expr con (Prod { repr_tup_tc = tup_tc
- , repr_comp_tys = tys
- , repr_comps = comps
- })
- = do vars <- newLocalVars (fsLit "y") tys
- es <- zipWithM from_comp (map Var vars) comps
- let [tup_con] = tyConDataCons tup_tc
- return $ mkWildCase expr (exprType expr) res_ty
- [(DataAlt tup_con, vars, con `mkApps` es)]
-
- from_comp expr (Keep _ _) = return expr
- from_comp expr (Wrap ty) = unwrapNewTypeBodyOfWrap expr ty
-
-
--- buildToArrRepr -------------------------------------------------------------
-
--- |Build the 'toArrRepr' method of the PA class.
---
-buildToArrPRepr :: PAInstanceBuilder
-buildToArrPRepr vect_tc repr_co pdata_tc _ r
- = do arg_ty <- mkPDataType el_ty
- res_ty <- mkPDataType =<< mkPReprType el_ty
- arg <- newLocalVar (fsLit "xs") arg_ty
-
- pdata_co <- mkBuiltinCo pdataTyCon
- let co = mkAppCo pdata_co
- $ mkSymCo
- $ mkUnbranchedAxInstCo Nominal repr_co ty_args []
-
- scrut = unwrapFamInstScrut pdata_tc ty_args (Var arg)
-
- (vars, result) <- to_sum r
-
- return . Lam arg
- $ mkWildCase scrut (mkTyConApp pdata_tc ty_args) res_ty
- [(DataAlt pdata_dc, vars, mkCast result co)]
- where
- ty_args = mkTyVarTys $ tyConTyVars vect_tc
- el_ty = mkTyConApp vect_tc ty_args
- [pdata_dc] = tyConDataCons pdata_tc
-
- to_sum ss
- = case ss of
- EmptySum -> builtin pvoidVar >>= \pvoid -> return ([], Var pvoid)
- UnarySum r -> to_con r
- Sum{}
- -> do let psum_tc = repr_psum_tc ss
- let [psum_con] = tyConDataCons psum_tc
- (vars, exprs) <- mapAndUnzipM to_con (repr_cons ss)
- sel <- newLocalVar (fsLit "sel") (repr_sel_ty ss)
- return ( sel : concat vars
- , wrapFamInstBody psum_tc (repr_con_tys ss)
- $ mkConApp psum_con
- $ map Type (repr_con_tys ss) ++ (Var sel : exprs))
-
- to_prod ss
- = case ss of
- EmptyProd -> builtin pvoidVar >>= \pvoid -> return ([], Var pvoid)
- UnaryProd r
- -> do pty <- mkPDataType (compOrigType r)
- var <- newLocalVar (fsLit "x") pty
- expr <- to_comp (Var var) r
- return ([var], expr)
- Prod{}
- -> do let [ptup_con] = tyConDataCons (repr_ptup_tc ss)
- ptys <- mapM (mkPDataType . compOrigType) (repr_comps ss)
- vars <- newLocalVars (fsLit "x") ptys
- exprs <- zipWithM to_comp (map Var vars) (repr_comps ss)
- return ( vars
- , wrapFamInstBody (repr_ptup_tc ss) (repr_comp_tys ss)
- $ mkConApp ptup_con
- $ map Type (repr_comp_tys ss) ++ exprs)
-
- to_con (ConRepr _ r) = to_prod r
-
- to_comp expr (Keep _ _) = return expr
- to_comp expr (Wrap ty) = wrapNewTypeBodyOfPDataWrap expr ty
-
-
--- buildFromArrPRepr ----------------------------------------------------------
-
--- |Build the 'fromArrPRepr' method for the PA class.
---
-buildFromArrPRepr :: PAInstanceBuilder
-buildFromArrPRepr vect_tc repr_co pdata_tc _ r
- = do arg_ty <- mkPDataType =<< mkPReprType el_ty
- res_ty <- mkPDataType el_ty
- arg <- newLocalVar (fsLit "xs") arg_ty
-
- pdata_co <- mkBuiltinCo pdataTyCon
- let co = mkAppCo pdata_co
- $ mkUnbranchedAxInstCo Nominal repr_co var_tys []
-
- let scrut = mkCast (Var arg) co
-
- let mk_result args
- = wrapFamInstBody pdata_tc var_tys
- $ mkConApp pdata_con
- $ map Type var_tys ++ args
-
- (expr, _) <- fixV $ \ ~(_, args) ->
- from_sum res_ty (mk_result args) scrut r
-
- return $ Lam arg expr
- where
- var_tys = mkTyVarTys $ tyConTyVars vect_tc
- el_ty = mkTyConApp vect_tc var_tys
- [pdata_con] = tyConDataCons pdata_tc
-
- from_sum res_ty res expr ss
- = case ss of
- EmptySum -> return (res, [])
- UnarySum r -> from_con res_ty res expr r
- Sum {}
- -> do let psum_tc = repr_psum_tc ss
- let [psum_con] = tyConDataCons psum_tc
- sel <- newLocalVar (fsLit "sel") (repr_sel_ty ss)
- ptys <- mapM mkPDataType (repr_con_tys ss)
- vars <- newLocalVars (fsLit "xs") ptys
- (res', args) <- fold from_con res_ty res (map Var vars) (repr_cons ss)
- let scrut = unwrapFamInstScrut psum_tc (repr_con_tys ss) expr
- let body = mkWildCase scrut (exprType scrut) res_ty
- [(DataAlt psum_con, sel : vars, res')]
- return (body, Var sel : args)
-
- from_prod res_ty res expr ss
- = case ss of
- EmptyProd -> return (res, [])
- UnaryProd r -> from_comp res_ty res expr r
- Prod {}
- -> do let ptup_tc = repr_ptup_tc ss
- let [ptup_con] = tyConDataCons ptup_tc
- ptys <- mapM mkPDataType (repr_comp_tys ss)
- vars <- newLocalVars (fsLit "ys") ptys
- (res', args) <- fold from_comp res_ty res (map Var vars) (repr_comps ss)
- let scrut = unwrapFamInstScrut ptup_tc (repr_comp_tys ss) expr
- let body = mkWildCase scrut (exprType scrut) res_ty
- [(DataAlt ptup_con, vars, res')]
- return (body, args)
-
- from_con res_ty res expr (ConRepr _ r) = from_prod res_ty res expr r
-
- from_comp _ res expr (Keep _ _) = return (res, [expr])
- from_comp _ res expr (Wrap ty) = do { expr' <- unwrapNewTypeBodyOfPDataWrap expr ty
- ; return (res, [expr'])
- }
-
- fold f res_ty res exprs rs
- = foldrM f' (res, []) (zip exprs rs)
- where
- f' (expr, r) (res, args)
- = do (res', args') <- f res_ty res expr r
- return (res', args' ++ args)
-
-
--- buildToArrPReprs -----------------------------------------------------------
--- | Build the 'toArrPReprs' instance for the PA class.
--- This converts a PData of elements into the generic representation.
-buildToArrPReprs :: PAInstanceBuilder
-buildToArrPReprs vect_tc repr_co _ pdatas_tc r
- = do
- -- The argument type of the instance.
- -- eg: 'PDatas (Tree a b)'
- arg_ty <- mkPDatasType el_ty
-
- -- The result type.
- -- eg: 'PDatas (PRepr (Tree a b))'
- res_ty <- mkPDatasType =<< mkPReprType el_ty
-
- -- Variable to bind the argument to the instance
- -- eg: (xss :: PDatas (Tree a b))
- varg <- newLocalVar (fsLit "xss") arg_ty
-
- -- Coercion to case between the (PRepr a) type and its instance.
- pdatas_co <- mkBuiltinCo pdatasTyCon
- let co = mkAppCo pdatas_co
- $ mkSymCo
- $ mkUnbranchedAxInstCo Nominal repr_co ty_args []
-
- let scrut = unwrapFamInstScrut pdatas_tc ty_args (Var varg)
- (vars, result) <- to_sum r
-
- return $ Lam varg
- $ mkWildCase scrut (mkTyConApp pdatas_tc ty_args) res_ty
- [(DataAlt pdatas_dc, vars, mkCast result co)]
-
- where
- -- The element type of the argument.
- -- eg: 'Tree a b'.
- ty_args = mkTyVarTys $ tyConTyVars vect_tc
- el_ty = mkTyConApp vect_tc ty_args
-
- -- PDatas data constructor
- [pdatas_dc] = tyConDataCons pdatas_tc
-
- to_sum ss
- = case ss of
- -- We can't convert data types with no data.
- -- See Note: [Empty PDatas].
- EmptySum -> do dflags <- getDynFlags
- return ([], errorEmptyPDatas dflags el_ty)
- UnarySum r -> do dflags <- getDynFlags
- to_con (errorEmptyPDatas dflags el_ty) r
-
- Sum{}
- -> do let psums_tc = repr_psums_tc ss
- let [psums_con] = tyConDataCons psums_tc
- sels <- newLocalVar (fsLit "sels") (repr_sels_ty ss)
-
- -- Take the number of selectors to serve as the length of
- -- and PDatas Void arrays in the product. See Note [Empty PDatas].
- let xSums = App (repr_selsLength_v ss) (Var sels)
-
- xSums_var <- newLocalVar (fsLit "xsum") intPrimTy
-
- (vars, exprs) <- mapAndUnzipM (to_con xSums_var) (repr_cons ss)
- return ( sels : concat vars
- , wrapFamInstBody psums_tc (repr_con_tys ss)
- $ mkCoreLet (NonRec xSums_var xSums)
- -- mkCoreLet ensures that the let/app invariant holds
- $ mkConApp psums_con
- $ map Type (repr_con_tys ss) ++ (Var sels : exprs))
-
- to_prod xSums ss
- = case ss of
- EmptyProd
- -> do pvoids <- builtin pvoidsVar
- return ([], App (Var pvoids) (Var xSums) )
-
- UnaryProd r
- -> do pty <- mkPDatasType (compOrigType r)
- var <- newLocalVar (fsLit "x") pty
- expr <- to_comp (Var var) r
- return ([var], expr)
-
- Prod{}
- -> do let [ptups_con] = tyConDataCons (repr_ptups_tc ss)
- ptys <- mapM (mkPDatasType . compOrigType) (repr_comps ss)
- vars <- newLocalVars (fsLit "x") ptys
- exprs <- zipWithM to_comp (map Var vars) (repr_comps ss)
- return ( vars
- , wrapFamInstBody (repr_ptups_tc ss) (repr_comp_tys ss)
- $ mkConApp ptups_con
- $ map Type (repr_comp_tys ss) ++ exprs)
-
- to_con xSums (ConRepr _ r)
- = to_prod xSums r
-
- to_comp expr (Keep _ _) = return expr
- to_comp expr (Wrap ty) = wrapNewTypeBodyOfPDatasWrap expr ty
-
-
--- buildFromArrPReprs ---------------------------------------------------------
-buildFromArrPReprs :: PAInstanceBuilder
-buildFromArrPReprs vect_tc repr_co _ pdatas_tc r
- = do
- -- The argument type of the instance.
- -- eg: 'PDatas (PRepr (Tree a b))'
- arg_ty <- mkPDatasType =<< mkPReprType el_ty
-
- -- The result type.
- -- eg: 'PDatas (Tree a b)'
- res_ty <- mkPDatasType el_ty
-
- -- Variable to bind the argument to the instance
- -- eg: (xss :: PDatas (PRepr (Tree a b)))
- varg <- newLocalVar (fsLit "xss") arg_ty
-
- -- Build the coercion between PRepr and the instance type
- pdatas_co <- mkBuiltinCo pdatasTyCon
- let co = mkAppCo pdatas_co
- $ mkUnbranchedAxInstCo Nominal repr_co var_tys []
-
- let scrut = mkCast (Var varg) co
-
- let mk_result args
- = wrapFamInstBody pdatas_tc var_tys
- $ mkConApp pdatas_con
- $ map Type var_tys ++ args
-
- (expr, _) <- fixV $ \ ~(_, args) ->
- from_sum res_ty (mk_result args) scrut r
-
- return $ Lam varg expr
- where
- -- The element type of the argument.
- -- eg: 'Tree a b'.
- ty_args = mkTyVarTys $ tyConTyVars vect_tc
- el_ty = mkTyConApp vect_tc ty_args
-
- var_tys = mkTyVarTys $ tyConTyVars vect_tc
- [pdatas_con] = tyConDataCons pdatas_tc
-
- from_sum res_ty res expr ss
- = case ss of
- -- We can't convert data types with no data.
- -- See Note: [Empty PDatas].
- EmptySum -> do dflags <- getDynFlags
- return (res, errorEmptyPDatas dflags el_ty)
- UnarySum r -> from_con res_ty res expr r
-
- Sum {}
- -> do let psums_tc = repr_psums_tc ss
- let [psums_con] = tyConDataCons psums_tc
- sel <- newLocalVar (fsLit "sels") (repr_sels_ty ss)
- ptys <- mapM mkPDatasType (repr_con_tys ss)
- vars <- newLocalVars (fsLit "xs") ptys
- (res', args) <- fold from_con res_ty res (map Var vars) (repr_cons ss)
- let scrut = unwrapFamInstScrut psums_tc (repr_con_tys ss) expr
- let body = mkWildCase scrut (exprType scrut) res_ty
- [(DataAlt psums_con, sel : vars, res')]
- return (body, Var sel : args)
-
- from_prod res_ty res expr ss
- = case ss of
- EmptyProd -> return (res, [])
- UnaryProd r -> from_comp res_ty res expr r
- Prod {}
- -> do let ptups_tc = repr_ptups_tc ss
- let [ptups_con] = tyConDataCons ptups_tc
- ptys <- mapM mkPDatasType (repr_comp_tys ss)
- vars <- newLocalVars (fsLit "ys") ptys
- (res', args) <- fold from_comp res_ty res (map Var vars) (repr_comps ss)
- let scrut = unwrapFamInstScrut ptups_tc (repr_comp_tys ss) expr
- let body = mkWildCase scrut (exprType scrut) res_ty
- [(DataAlt ptups_con, vars, res')]
- return (body, args)
-
- from_con res_ty res expr (ConRepr _ r)
- = from_prod res_ty res expr r
-
- from_comp _ res expr (Keep _ _) = return (res, [expr])
- from_comp _ res expr (Wrap ty) = do { expr' <- unwrapNewTypeBodyOfPDatasWrap expr ty
- ; return (res, [expr'])
- }
-
- fold f res_ty res exprs rs
- = foldrM f' (res, []) (zip exprs rs)
- where
- f' (expr, r) (res, args)
- = do (res', args') <- f res_ty res expr r
- return (res', args' ++ args)
-
-
--- Notes ----------------------------------------------------------------------
-{-
-Note [Empty PDatas]
-~~~~~~~~~~~~~~~~~~~
-We don't support "empty" data types like the following:
-
- data Empty0
- data Empty1 = MkEmpty1
- data Empty2 = MkEmpty2 Empty0
- ...
-
-There is no parallel data associcated with these types, so there is no where
-to store the length of the PDatas array with our standard representation.
-
-Enumerations like the following are ok:
- data Bool = True | False
-
-The native and generic representations are:
- type instance (PDatas Bool) = VPDs:Bool Sels2
- type instance (PDatas (Repr Bool)) = PSum2s Sels2 (PDatas Void) (PDatas Void)
-
-To take the length of a (PDatas Bool) we take the length of the contained Sels2.
-When converting a (PDatas Bool) to a (PDatas (Repr Bool)) we use this length to
-initialise the two (PDatas Void) arrays.
-
-However, with this:
- data Empty1 = MkEmpty1
-
-The native and generic representations would be:
- type instance (PDatas Empty1) = VPDs:Empty1
- type instance (PDatas (Repr Empty1)) = PVoids Int
-
-The 'Int' argument of PVoids is supposed to store the length of the PDatas
-array. When converting the (PDatas Empty1) to a (PDatas (Repr Empty1)) we
-need to come up with a value for it, but there isn't one.
-
-To fix this we'd need to add an Int field to VPDs:Empty1 as well, but that's
-too much hassle and there's no point running a parallel computation on no
-data anyway.
--}
-errorEmptyPDatas :: DynFlags -> Type -> a
-errorEmptyPDatas dflags tc
- = cantVectorise dflags "Vectorise.PAMethods"
- $ vcat [ text "Cannot vectorise data type with no parallel data " <> quotes (ppr tc)
- , text "Data types to be vectorised must contain at least one constructor"
- , text "with at least one field." ]