Allow variables to be mapped to arbitrary CoreExprs in vectorisation monad
[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 TyCon
12 import Type
13 import TypeRep
14 import Var
15 import VarEnv
16 import Name                 ( mkSysTvName )
17 import NameEnv
18
19 import DsMonad
20
21 import PrelNames
22
23 import Outputable
24 import FastString
25 import Control.Monad        ( liftM2 )
26
27 vectorise :: HscEnv -> ModGuts -> IO ModGuts
28 vectorise hsc_env guts
29   | not (Opt_Vectorise `dopt` dflags) = return guts
30   | otherwise
31   = do
32       showPass dflags "Vectorisation"
33       eps <- hscEPS hsc_env
34       let info = hptVectInfo hsc_env `plusVectInfo` eps_vect_info eps
35       Just guts' <- initDs hsc_env (mg_module guts)
36                                    (mg_rdr_env guts)
37                                    (mg_types guts)
38                                    (vectoriseModule info guts)
39       endPass dflags "Vectorisation" Opt_D_dump_vect (mg_binds guts')
40       return guts'
41   where
42     dflags = hsc_dflags hsc_env
43
44 -- ----------------------------------------------------------------------------
45 -- Vectorisation monad
46
47 data Builtins = Builtins {
48                   parrayTyCon      :: TyCon
49                 , paTyCon          :: TyCon
50                 , closureTyCon     :: TyCon
51                 , mkClosureVar     :: Var
52                 , applyClosureVar  :: Var
53                 , mkClosurePVar    :: Var
54                 , applyClosurePVar :: Var
55                 , closurePAVar     :: Var
56                 , lengthPAVar      :: Var
57                 , replicatePAVar   :: Var
58                 }
59
60 initBuiltins :: DsM Builtins
61 initBuiltins
62   = do
63       parrayTyCon  <- dsLookupTyCon parrayTyConName
64       paTyCon      <- dsLookupTyCon paTyConName
65       closureTyCon <- dsLookupTyCon closureTyConName
66
67       mkClosureVar     <- dsLookupGlobalId mkClosureName
68       applyClosureVar  <- dsLookupGlobalId applyClosureName
69       mkClosurePVar    <- dsLookupGlobalId mkClosurePName
70       applyClosurePVar <- dsLookupGlobalId applyClosurePName
71       closurePAVar     <- dsLookupGlobalId closurePAName
72       lengthPAVar      <- dsLookupGlobalId lengthPAName
73       replicatePAVar   <- dsLookupGlobalId replicatePAName
74
75       return $ Builtins {
76                  parrayTyCon      = parrayTyCon
77                , paTyCon          = paTyCon
78                , closureTyCon     = closureTyCon
79                , mkClosureVar     = mkClosureVar
80                , applyClosureVar  = applyClosureVar
81                , mkClosurePVar    = mkClosurePVar
82                , applyClosurePVar = applyClosurePVar
83                , closurePAVar     = closurePAVar
84                , lengthPAVar      = lengthPAVar
85                , replicatePAVar   = replicatePAVar
86                }
87
88 data VEnv = VEnv {
89               -- Mapping from variables to their vectorised versions. Mapping
90               -- to expressions instead of just Vars gives us more freedom.
91               -- 
92               vect_vars :: VarEnv CoreExpr
93
94               -- Exported variables which have a vectorised version
95               --
96             , vect_exported_vars :: VarEnv (Var, Var)
97
98               -- Mapping from TyCons to their vectorised versions.
99               -- TyCons which do not have to be vectorised are mapped to
100               -- themselves.
101             , vect_tycons :: NameEnv TyCon
102             }
103
104 initVEnv :: VectInfo -> DsM VEnv
105 initVEnv info
106   = return $ VEnv {
107                vect_vars          = mapVarEnv  (Var . snd) $ vectInfoCCVar   info
108              , vect_exported_vars = emptyVarEnv
109              , vect_tycons        = mapNameEnv snd $ vectInfoCCTyCon info
110              }
111
112 -- FIXME
113 updVectInfo :: VEnv -> ModGuts -> ModGuts
114 updVectInfo env guts = guts { mg_vect_info = info' }
115   where
116     info' = info {
117               vectInfoCCVar   = vect_exported_vars env
118             , vectInfoCCTyCon = tc_env
119             }
120
121     info  = mg_vect_info guts
122     tyenv = mg_types guts
123
124     tc_env = mkNameEnv [(tc_name, (tc,tc')) | tc <- typeEnvTyCons tyenv
125                                             , let tc_name = tyConName tc
126                                             , Just tc' <- [lookupNameEnv (vect_tycons env) tc_name]]
127
128 data VResult a = Yes VEnv a | No
129
130 newtype VM a = VM { runVM :: Builtins -> VEnv -> DsM (VResult a) }
131
132 instance Monad VM where
133   return x   = VM $ \bi env -> return (Yes env x)
134   VM p >>= f = VM $ \bi env -> do
135                                  r <- p bi env
136                                  case r of
137                                    Yes env' x -> runVM (f x) bi env'
138                                    No         -> return No
139
140 noV :: VM a
141 noV = VM $ \bi env -> return No
142
143 tryV :: VM a -> VM (Maybe a)
144 tryV (VM p) = VM $ \bi env -> do
145                                 r <- p bi env
146                                 case r of
147                                   Yes env' x -> return (Yes env' (Just x))
148                                   No         -> return (Yes env Nothing)
149
150 maybeV :: VM (Maybe a) -> VM a
151 maybeV p = maybe noV return =<< p
152
153 liftDs :: DsM a -> VM a
154 liftDs p = VM $ \bi env -> do { x <- p; return (Yes env x) }
155
156 builtin :: (Builtins -> a) -> VM a
157 builtin f = VM $ \bi env -> return (Yes env (f bi))
158
159 readEnv :: (VEnv -> a) -> VM a
160 readEnv f = VM $ \bi env -> return (Yes env (f env))
161
162 setEnv :: VEnv -> VM ()
163 setEnv env = VM $ \_ _ -> return (Yes env ())
164
165 updEnv :: (VEnv -> VEnv) -> VM ()
166 updEnv f = VM $ \_ env -> return (Yes (f env) ())
167
168 newTyVar :: FastString -> Kind -> VM Var
169 newTyVar fs k
170   = do
171       u <- liftDs newUnique
172       return $ mkTyVar (mkSysTvName u fs) k
173
174 lookupVar :: Var -> VM CoreExpr
175 lookupVar v = maybeV . readEnv $ \env -> lookupVarEnv (vect_vars env) v
176
177 lookupTyCon :: TyCon -> VM (Maybe TyCon)
178 lookupTyCon tc = readEnv $ \env -> lookupNameEnv (vect_tycons env) (tyConName tc)
179
180 -- ----------------------------------------------------------------------------
181 -- Bindings
182
183 vectoriseModule :: VectInfo -> ModGuts -> DsM ModGuts
184 vectoriseModule info guts
185   = do
186       builtins <- initBuiltins
187       env <- initVEnv info
188       r <- runVM (vectModule guts) builtins env
189       case r of
190         Yes env' guts' -> return $ updVectInfo env' guts'
191         No             -> return guts
192
193 vectModule :: ModGuts -> VM ModGuts
194 vectModule guts = return guts
195
196 -- ----------------------------------------------------------------------------
197 -- Types
198
199 paArgType :: Type -> Kind -> VM (Maybe Type)
200 paArgType ty k
201   | Just k' <- kindView k = paArgType ty k'
202
203 -- Here, we assume that for a kind (k1 -> k2) to be valid, k1 and k2 can only
204 -- be made up of * and (->), i.e., they can't be coercion kinds or #.
205 paArgType ty (FunTy k1 k2)
206   = do
207       tv  <- newTyVar FSLIT("a") k1
208       ty1 <- paArgType' (TyVarTy tv) k1
209       ty2 <- paArgType' (AppTy ty (TyVarTy tv)) k2
210       return . Just $ ForAllTy tv (FunTy ty1 ty2)
211
212 paArgType ty k
213   | isLiftedTypeKind k
214   = do
215       tc <- builtin paTyCon
216       return . Just $ TyConApp tc [ty]
217
218   | otherwise
219   = return Nothing 
220
221 paArgType' :: Type -> Kind -> VM Type
222 paArgType' ty k
223   = do
224       r <- paArgType ty k
225       case r of
226         Just ty' -> return ty'
227         Nothing  -> pprPanic "paArgType'" (ppr ty)
228
229 vectTyCon :: TyCon -> VM TyCon
230 vectTyCon tc
231   | isFunTyCon tc        = builtin closureTyCon
232   | isBoxedTupleTyCon tc = return tc
233   | isUnLiftedTyCon tc   = return tc
234   | otherwise = do
235                   r <- lookupTyCon tc
236                   case r of
237                     Just tc' -> return tc'
238
239                     -- FIXME: just for now
240                     Nothing  -> pprTrace "ccTyCon:" (ppr tc) $ return tc
241
242 vectType :: Type -> VM Type
243 vectType ty | Just ty' <- coreView ty = vectType ty
244 vectType (TyVarTy tv) = return $ TyVarTy tv
245 vectType (AppTy ty1 ty2) = liftM2 AppTy (vectType ty1) (vectType ty2)
246 vectType (TyConApp tc tys) = liftM2 TyConApp (vectTyCon tc) (mapM vectType tys)
247 vectType (FunTy ty1 ty2)   = liftM2 TyConApp (builtin closureTyCon)
248                                              (mapM vectType [ty1,ty2])
249 vectType (ForAllTy tv ty)
250   = do
251       r   <- paArgType (TyVarTy tv) (tyVarKind tv)
252       ty' <- vectType ty
253       return . ForAllTy tv $ case r of { Just paty -> FunTy paty ty'; Nothing -> ty' }
254
255 vectType ty = pprPanic "vectType:" (ppr ty)
256