First cut at vectorisation of expressions
[ghc-hetmet.git] / compiler / vectorise / Vectorise.hs
1 module Vectorise( vectorise )
2 where
3
4 #include "HsVersions.h"
5
6 import DynFlags
7 import HscTypes
8
9 import CoreLint             ( showPass, endPass )
10 import CoreSyn
11 import CoreUtils
12 import CoreFVs
13 import TyCon
14 import Type
15 import TypeRep
16 import Var
17 import VarEnv
18 import Name                 ( mkSysTvName )
19 import NameEnv
20
21 import DsMonad
22
23 import PrelNames
24
25 import Outputable
26 import FastString
27 import Control.Monad        ( liftM2 )
28
29 vectorise :: HscEnv -> ModGuts -> IO ModGuts
30 vectorise hsc_env guts
31   | not (Opt_Vectorise `dopt` dflags) = return guts
32   | otherwise
33   = do
34       showPass dflags "Vectorisation"
35       eps <- hscEPS hsc_env
36       let info = hptVectInfo hsc_env `plusVectInfo` eps_vect_info eps
37       Just guts' <- initDs hsc_env (mg_module guts)
38                                    (mg_rdr_env guts)
39                                    (mg_types guts)
40                                    (vectoriseModule info guts)
41       endPass dflags "Vectorisation" Opt_D_dump_vect (mg_binds guts')
42       return guts'
43   where
44     dflags = hsc_dflags hsc_env
45
46 -- ----------------------------------------------------------------------------
47 -- Vectorisation monad
48
49 data Builtins = Builtins {
50                   parrayTyCon      :: TyCon
51                 , paTyCon          :: TyCon
52                 , closureTyCon     :: TyCon
53                 , mkClosureVar     :: Var
54                 , applyClosureVar  :: Var
55                 , mkClosurePVar    :: Var
56                 , applyClosurePVar :: Var
57                 , closurePAVar     :: Var
58                 , lengthPAVar      :: Var
59                 , replicatePAVar   :: Var
60                 }
61
62 initBuiltins :: DsM Builtins
63 initBuiltins
64   = do
65       parrayTyCon  <- dsLookupTyCon parrayTyConName
66       paTyCon      <- dsLookupTyCon paTyConName
67       closureTyCon <- dsLookupTyCon closureTyConName
68
69       mkClosureVar     <- dsLookupGlobalId mkClosureName
70       applyClosureVar  <- dsLookupGlobalId applyClosureName
71       mkClosurePVar    <- dsLookupGlobalId mkClosurePName
72       applyClosurePVar <- dsLookupGlobalId applyClosurePName
73       closurePAVar     <- dsLookupGlobalId closurePAName
74       lengthPAVar      <- dsLookupGlobalId lengthPAName
75       replicatePAVar   <- dsLookupGlobalId replicatePAName
76
77       return $ Builtins {
78                  parrayTyCon      = parrayTyCon
79                , paTyCon          = paTyCon
80                , closureTyCon     = closureTyCon
81                , mkClosureVar     = mkClosureVar
82                , applyClosureVar  = applyClosureVar
83                , mkClosurePVar    = mkClosurePVar
84                , applyClosurePVar = applyClosurePVar
85                , closurePAVar     = closurePAVar
86                , lengthPAVar      = lengthPAVar
87                , replicatePAVar   = replicatePAVar
88                }
89
90 data VEnv = VEnv {
91               -- Mapping from global variables to their vectorised versions.
92               -- 
93               vect_global_vars :: VarEnv CoreExpr
94
95               -- Mapping from local variables to their vectorised and lifted
96               -- versions.
97               --
98             , vect_local_vars :: VarEnv (CoreExpr, CoreExpr)
99
100               -- Exported variables which have a vectorised version
101               --
102             , vect_exported_vars :: VarEnv (Var, Var)
103
104               -- Mapping from TyCons to their vectorised versions.
105               -- TyCons which do not have to be vectorised are mapped to
106               -- themselves.
107               --
108             , vect_tycons :: NameEnv TyCon
109
110               -- Mapping from TyCons to their PA dictionaries
111               --
112             , vect_tycon_pa :: NameEnv CoreExpr
113
114               -- Mapping from tyvars to their PA dictionaries
115               --
116             , vect_tyvar_pa :: VarEnv CoreExpr
117             }
118
119 initVEnv :: VectInfo -> DsM VEnv
120 initVEnv info
121   = return $ VEnv {
122                vect_global_vars   = mapVarEnv  (Var . snd) $ vectInfoCCVar   info
123              , vect_local_vars    = emptyVarEnv
124              , vect_exported_vars = emptyVarEnv
125              , vect_tycons        = mapNameEnv snd $ vectInfoCCTyCon info
126              , vect_tycon_pa      = emptyNameEnv
127              , vect_tyvar_pa      = emptyVarEnv
128              }
129
130 -- FIXME
131 updVectInfo :: VEnv -> ModGuts -> ModGuts
132 updVectInfo env guts = guts { mg_vect_info = info' }
133   where
134     info' = info {
135               vectInfoCCVar   = vect_exported_vars env
136             , vectInfoCCTyCon = tc_env
137             }
138
139     info  = mg_vect_info guts
140     tyenv = mg_types guts
141
142     tc_env = mkNameEnv [(tc_name, (tc,tc')) | tc <- typeEnvTyCons tyenv
143                                             , let tc_name = tyConName tc
144                                             , Just tc' <- [lookupNameEnv (vect_tycons env) tc_name]]
145
146 data VResult a = Yes VEnv a | No
147
148 newtype VM a = VM { runVM :: Builtins -> VEnv -> DsM (VResult a) }
149
150 instance Monad VM where
151   return x   = VM $ \bi env -> return (Yes env x)
152   VM p >>= f = VM $ \bi env -> do
153                                  r <- p bi env
154                                  case r of
155                                    Yes env' x -> runVM (f x) bi env'
156                                    No         -> return No
157
158 noV :: VM a
159 noV = VM $ \bi env -> return No
160
161 tryV :: VM a -> VM (Maybe a)
162 tryV (VM p) = VM $ \bi env -> do
163                                 r <- p bi env
164                                 case r of
165                                   Yes env' x -> return (Yes env' (Just x))
166                                   No         -> return (Yes env Nothing)
167
168 maybeV :: VM (Maybe a) -> VM a
169 maybeV p = maybe noV return =<< p
170
171 orElseV :: VM a -> VM a -> VM a
172 orElseV p q = maybe q return =<< tryV p
173
174 liftDs :: DsM a -> VM a
175 liftDs p = VM $ \bi env -> do { x <- p; return (Yes env x) }
176
177 builtin :: (Builtins -> a) -> VM a
178 builtin f = VM $ \bi env -> return (Yes env (f bi))
179
180 readEnv :: (VEnv -> a) -> VM a
181 readEnv f = VM $ \bi env -> return (Yes env (f env))
182
183 setEnv :: VEnv -> VM ()
184 setEnv env = VM $ \_ _ -> return (Yes env ())
185
186 updEnv :: (VEnv -> VEnv) -> VM ()
187 updEnv f = VM $ \_ env -> return (Yes (f env) ())
188
189 newTyVar :: FastString -> Kind -> VM Var
190 newTyVar fs k
191   = do
192       u <- liftDs newUnique
193       return $ mkTyVar (mkSysTvName u fs) k
194
195 lookupTyCon :: TyCon -> VM (Maybe TyCon)
196 lookupTyCon tc = readEnv $ \env -> lookupNameEnv (vect_tycons env) (tyConName tc)
197
198 -- ----------------------------------------------------------------------------
199 -- Bindings
200
201 vectoriseModule :: VectInfo -> ModGuts -> DsM ModGuts
202 vectoriseModule info guts
203   = do
204       builtins <- initBuiltins
205       env <- initVEnv info
206       r <- runVM (vectModule guts) builtins env
207       case r of
208         Yes env' guts' -> return $ updVectInfo env' guts'
209         No             -> return guts
210
211 vectModule :: ModGuts -> VM ModGuts
212 vectModule guts = return guts
213
214 -- ----------------------------------------------------------------------------
215 -- Expressions
216
217 replicateP :: CoreExpr -> CoreExpr -> VM CoreExpr
218 replicateP expr len
219   = do
220       pa  <- paOfType ty
221       rep <- builtin replicatePAVar
222       return $ mkApps (Var rep) [Type ty, pa, expr, len]
223   where
224     ty = exprType expr
225
226 capply :: (CoreExpr, CoreExpr) -> (CoreExpr, CoreExpr) -> VM (CoreExpr, CoreExpr)
227 capply (vfn, lfn) (varg, larg)
228   = do
229       apply  <- builtin applyClosureVar
230       applyP <- builtin applyClosurePVar
231       return (mkApps (Var apply)  [Type arg_ty, Type res_ty, vfn, varg],
232               mkApps (Var applyP) [Type arg_ty, Type res_ty, lfn, larg])
233   where
234     fn_ty            = exprType vfn
235     (arg_ty, res_ty) = splitClosureTy fn_ty
236
237 vectVar :: CoreExpr -> Var -> VM (CoreExpr, CoreExpr)
238 vectVar lc v = local v `orElseV` global v
239   where
240     local  v = maybeV (readEnv $ \env -> lookupVarEnv (vect_local_vars env) v)
241     global v = do
242                  vexpr <- maybeV (readEnv $ \env -> lookupVarEnv (vect_global_vars env) v)
243                  lexpr <- replicateP vexpr lc
244                  return (vexpr, lexpr)
245                 
246 vectExpr :: CoreExpr -> CoreExprWithFVs -> VM (CoreExpr, CoreExpr)
247 vectExpr lc (_, AnnType ty)
248   = do
249       vty <- vectType ty
250       return (Type vty, Type vty)
251 vectExpr lc (_, AnnVar v)   = vectVar lc v
252 vectExpr lc (_, AnnLit lit)
253   = do
254       let vexpr = Lit lit
255       lexpr <- replicateP vexpr lc
256       return (vexpr, lexpr)
257 vectExpr lc (_, AnnNote note expr)
258   = do
259       (vexpr, lexpr) <- vectExpr lc expr
260       return (Note note vexpr, Note note lexpr)
261 vectExpr lc (_, AnnApp fn arg)
262   = do
263       fn'  <- vectExpr lc fn
264       arg' <- vectExpr lc arg
265       capply fn' arg'
266
267 -- ----------------------------------------------------------------------------
268 -- PA dictionaries
269
270 paArgType :: Type -> Kind -> VM (Maybe Type)
271 paArgType ty k
272   | Just k' <- kindView k = paArgType ty k'
273
274 -- Here, we assume that for a kind (k1 -> k2) to be valid, k1 and k2 can only
275 -- be made up of * and (->), i.e., they can't be coercion kinds or #.
276 paArgType ty (FunTy k1 k2)
277   = do
278       tv  <- newTyVar FSLIT("a") k1
279       ty1 <- paArgType' (TyVarTy tv) k1
280       ty2 <- paArgType' (AppTy ty (TyVarTy tv)) k2
281       return . Just $ ForAllTy tv (FunTy ty1 ty2)
282
283 paArgType ty k
284   | isLiftedTypeKind k
285   = do
286       tc <- builtin paTyCon
287       return . Just $ TyConApp tc [ty]
288
289   | otherwise
290   = return Nothing 
291
292 paArgType' :: Type -> Kind -> VM Type
293 paArgType' ty k
294   = do
295       r <- paArgType ty k
296       case r of
297         Just ty' -> return ty'
298         Nothing  -> pprPanic "paArgType'" (ppr ty)
299
300 paOfTyCon :: TyCon -> VM CoreExpr
301 -- FIXME: just for now
302 paOfTyCon tc = maybeV (readEnv $ \env -> lookupNameEnv (vect_tycon_pa env) (tyConName tc))
303
304 paOfType :: Type -> VM CoreExpr
305 paOfType ty | Just ty' <- coreView ty = paOfType ty'
306
307 paOfType (TyVarTy tv) = maybeV (readEnv $ \env -> lookupVarEnv (vect_tyvar_pa env) tv)
308 paOfType (AppTy ty1 ty2)
309   = do
310       e1 <- paOfType ty1
311       e2 <- paOfType ty2
312       return $ mkApps e1 [Type ty2, e2]
313 paOfType (TyConApp tc tys)
314   = do
315       e  <- paOfTyCon tc
316       es <- mapM paOfType tys
317       return $ mkApps e [arg | (t,e) <- zip tys es, arg <- [Type t, e]]
318 paOfType (FunTy ty1 ty2) = paOfType (TyConApp funTyCon [ty1,ty2])
319 paOfType t@(ForAllTy tv ty) = pprPanic "paOfType:" (ppr t)
320 paOfType ty = pprPanic "paOfType:" (ppr ty)
321         
322
323
324 -- ----------------------------------------------------------------------------
325 -- Types
326
327 vectTyCon :: TyCon -> VM TyCon
328 vectTyCon tc
329   | isFunTyCon tc        = builtin closureTyCon
330   | isBoxedTupleTyCon tc = return tc
331   | isUnLiftedTyCon tc   = return tc
332   | otherwise = do
333                   r <- lookupTyCon tc
334                   case r of
335                     Just tc' -> return tc'
336
337                     -- FIXME: just for now
338                     Nothing  -> pprTrace "ccTyCon:" (ppr tc) $ return tc
339
340 vectType :: Type -> VM Type
341 vectType ty | Just ty' <- coreView ty = vectType ty
342 vectType (TyVarTy tv) = return $ TyVarTy tv
343 vectType (AppTy ty1 ty2) = liftM2 AppTy (vectType ty1) (vectType ty2)
344 vectType (TyConApp tc tys) = liftM2 TyConApp (vectTyCon tc) (mapM vectType tys)
345 vectType (FunTy ty1 ty2)   = liftM2 TyConApp (builtin closureTyCon)
346                                              (mapM vectType [ty1,ty2])
347 vectType (ForAllTy tv ty)
348   = do
349       r   <- paArgType (TyVarTy tv) (tyVarKind tv)
350       ty' <- vectType ty
351       return . ForAllTy tv $ case r of { Just paty -> FunTy paty ty'; Nothing -> ty' }
352
353 vectType ty = pprPanic "vectType:" (ppr ty)
354
355 isClosureTyCon :: TyCon -> Bool
356 isClosureTyCon tc = tyConUnique tc == closureTyConKey
357
358 splitClosureTy :: Type -> (Type, Type)
359 splitClosureTy ty
360   | Just (tc, [arg_ty, res_ty]) <- splitTyConApp_maybe ty
361   , isClosureTyCon tc
362   = (arg_ty, res_ty)
363
364   | otherwise = pprPanic "splitClosureTy" (ppr ty)
365