PageRenderTime 52ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/vectorise/Vectorise/Type/Env.hs

https://github.com/tibbe/ghc
Haskell | 451 lines | 221 code | 54 blank | 176 comment | 7 complexity | 72d1ccbe81eee8e47e9aef14a85a14c6 MD5 | raw file
  1. {-# LANGUAGE CPP #-}
  2. -- Vectorise a modules type and class declarations.
  3. --
  4. -- This produces new type constructors and family instances top be included in the module toplevel
  5. -- as well as bindings for worker functions, dfuns, and the like.
  6. module Vectorise.Type.Env (
  7. vectTypeEnv,
  8. ) where
  9. #include "HsVersions.h"
  10. import Vectorise.Env
  11. import Vectorise.Vect
  12. import Vectorise.Monad
  13. import Vectorise.Builtins
  14. import Vectorise.Type.TyConDecl
  15. import Vectorise.Type.Classify
  16. import Vectorise.Generic.PADict
  17. import Vectorise.Generic.PAMethods
  18. import Vectorise.Generic.PData
  19. import Vectorise.Generic.Description
  20. import Vectorise.Utils
  21. import CoreSyn
  22. import CoreUtils
  23. import CoreUnfold
  24. import DataCon
  25. import TyCon
  26. import CoAxiom
  27. import Type
  28. import FamInstEnv
  29. import Id
  30. import MkId
  31. import NameEnv
  32. import NameSet
  33. import UniqFM
  34. import OccName
  35. import Unique
  36. import Util
  37. import Outputable
  38. import DynFlags
  39. import FastString
  40. import MonadUtils
  41. import Control.Monad
  42. import Data.Maybe
  43. import Data.List
  44. -- Note [Pragmas to vectorise tycons]
  45. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  46. --
  47. -- All imported type constructors that are not mapped to a vectorised type in the vectorisation map
  48. -- (possibly because the defining module was not compiled with vectorisation) may be used in scalar
  49. -- code encapsulated in vectorised code. If a such a type constructor 'T' is a member of the
  50. -- 'Scalar' class (and hence also of 'PData' and 'PRepr'), it may also be used in vectorised code,
  51. -- where 'T' represents itself, but the representation of 'T' still remains opaque in vectorised
  52. -- code (i.e., it can only be used in scalar code).
  53. --
  54. -- An example is the treatment of 'Int'. 'Int's can be used in vectorised code and remain unchanged
  55. -- by vectorisation. However, the representation of 'Int' by the 'I#' data constructor wrapping an
  56. -- 'Int#' is not exposed in vectorised code. Instead, computations involving the representation need
  57. -- to be confined to scalar code.
  58. --
  59. -- VECTORISE pragmas for type constructors cover four different flavours of vectorising data type
  60. -- constructors:
  61. --
  62. -- (1) Data type constructor 'T' that together with its constructors 'Cn' may be used in vectorised
  63. -- code, where 'T' and the 'Cn' are automatically vectorised in the same manner as data types
  64. -- declared in a vectorised module. This includes the case where the vectoriser determines that
  65. -- the original representation of 'T' may be used in vectorised code (as it does not embed any
  66. -- parallel arrays.) This case is for type constructors that are *imported* from a non-
  67. -- vectorised module, but that we want to use with full vectorisation support.
  68. --
  69. -- An example is the treatment of 'Ordering' and '[]'. The former remains unchanged by
  70. -- vectorisation, whereas the latter is fully vectorised.
  71. --
  72. -- 'PData' and 'PRepr' instances are automatically generated by the vectoriser.
  73. --
  74. -- Type constructors declared with {-# VECTORISE type T #-} are treated in this manner.
  75. --
  76. -- (2) Data type constructor 'T' that may be used in vectorised code, where 'T' is represented by an
  77. -- explicitly given 'Tv', but the representation of 'T' is opaque in vectorised code (i.e., the
  78. -- constructors of 'T' may not occur in vectorised code).
  79. --
  80. -- An example is the treatment of '[::]'. The type '[::]' can be used in vectorised code and is
  81. -- vectorised to 'PArray'. However, the representation of '[::]' is not exposed in vectorised
  82. -- code. Instead, computations involving the representation need to be confined to scalar code.
  83. --
  84. -- 'PData' and 'PRepr' instances need to be explicitly supplied for 'T' (they are not generated
  85. -- by the vectoriser).
  86. --
  87. -- Type constructors declared with {-# VECTORISE type T = Tv #-} are treated in this manner
  88. -- manner. (The vectoriser never treats a type constructor automatically in this manner.)
  89. --
  90. -- (3) Data type constructor 'T' that does not contain any parallel arrays and has explicitly
  91. -- provided 'PData' and 'PRepr' instances (and maybe also a 'Scalar' instance), which together
  92. -- with the type's constructors 'Cn' may be used in vectorised code. The type 'T' and its
  93. -- constructors 'Cn' are represented by themselves in vectorised code.
  94. --
  95. -- An example is 'Bool', which is represented by itself in vectorised code (as it cannot embed
  96. -- any parallel arrays). However, we do not want any automatic generation of class and family
  97. -- instances, which is why Case (1) does not apply.
  98. --
  99. -- 'PData' and 'PRepr' instances need to be explicitly supplied for 'T' (they are not generated
  100. -- by the vectoriser).
  101. --
  102. -- Type constructors declared with {-# VECTORISE SCALAR type T #-} are treated in this manner.
  103. --
  104. -- (4) Data type constructor 'T' that does not contain any parallel arrays and that, in vectorised
  105. -- code, is represented by an explicitly given 'Tv', but the representation of 'T' is opaque in
  106. -- vectorised code and 'T' is regarded to be scalar i.e., it may be used in encapsulated
  107. -- scalar subcomputations.
  108. --
  109. -- An example is the treatment of '(->)'. Types '(->)' can be used in vectorised code and are
  110. -- vectorised to '(:->)'. However, the representation of '(->)' is not exposed in vectorised
  111. -- code. Instead, computations involving the representation need to be confined to scalar code
  112. -- and may be part of encapsulated scalar computations.
  113. --
  114. -- 'PData' and 'PRepr' instances need to be explicitly supplied for 'T' (they are not generated
  115. -- by the vectoriser).
  116. --
  117. -- Type constructors declared with {-# VECTORISE SCALAR type T = Tv #-} are treated in this
  118. -- manner. (The vectoriser never treats a type constructor automatically in this manner.)
  119. --
  120. -- In addition, we have also got a single pragma form for type classes: {-# VECTORISE class C #-}.
  121. -- It implies that the class type constructor may be used in vectorised code together with its data
  122. -- constructor. We generally produce a vectorised version of the data type and data constructor.
  123. -- We do not generate 'PData' and 'PRepr' instances for class type constructors. This pragma is the
  124. -- default for all type classes declared in a vectorised module, but the pragma can also be used
  125. -- explitly on imported classes.
  126. -- Note [Vectorising classes]
  127. -- ~~~~~~~~~~~~~~~~~~~~~~~~~~
  128. --
  129. -- We vectorise classes essentially by just vectorising their desugared Core representation, but we
  130. -- do generate a 'Class' structure along the way (see 'Vectorise.Type.TyConDecl.vectTyConDecl').
  131. --
  132. -- Here is an example illustrating the mapping assume
  133. --
  134. -- class Num a where
  135. -- (+) :: a -> a -> a
  136. --
  137. -- It desugars to
  138. --
  139. -- data Num a = D:Num { (+) :: a -> a -> a }
  140. --
  141. -- which we vectorise to
  142. --
  143. -- data V:Num a = D:V:Num { ($v+) :: PArray a :-> PArray a :-> PArray a }
  144. --
  145. -- while adding the following entries to the vectorisation map:
  146. --
  147. -- tycon : Num --> V:Num
  148. -- datacon: D:Num --> D:V:Num
  149. -- var : (+) --> ($v+)
  150. -- |Vectorise type constructor including class type constructors.
  151. --
  152. vectTypeEnv :: [TyCon] -- Type constructors defined in this module
  153. -> [CoreVect] -- All 'VECTORISE [SCALAR] type' declarations in this module
  154. -> [CoreVect] -- All 'VECTORISE class' declarations in this module
  155. -> VM ( [TyCon] -- old TyCons ++ new TyCons
  156. , [FamInst] -- New type family instances.
  157. , [(Var, CoreExpr)]) -- New top level bindings.
  158. vectTypeEnv tycons vectTypeDecls vectClassDecls
  159. = do { traceVt "** vectTypeEnv" $ ppr tycons
  160. ; let -- {-# VECTORISE type T -#} (ONLY the imported tycons)
  161. impVectTyCons = ( [tycon | VectType False tycon Nothing <- vectTypeDecls]
  162. ++ [tycon | VectClass tycon <- vectClassDecls])
  163. \\ tycons
  164. -- {-# VECTORISE type T = Tv -#} (imported & local tycons with an /RHS/)
  165. vectTyConsWithRHS = [ (tycon, rhs)
  166. | VectType False tycon (Just rhs) <- vectTypeDecls]
  167. -- {-# VECTORISE SCALAR type T = Tv -#} (imported & local tycons with an /RHS/)
  168. scalarTyConsWithRHS = [ (tycon, rhs)
  169. | VectType True tycon (Just rhs) <- vectTypeDecls]
  170. -- {-# VECTORISE SCALAR type T -#} (imported & local /scalar/ tycons without an RHS)
  171. scalarTyConsNoRHS = [tycon | VectType True tycon Nothing <- vectTypeDecls]
  172. -- Check that is not a VECTORISE SCALAR tycon nor VECTORISE tycons with explicit rhs?
  173. vectSpecialTyConNames = mkNameSet . map tyConName $
  174. scalarTyConsNoRHS ++
  175. map fst (vectTyConsWithRHS ++ scalarTyConsWithRHS)
  176. notVectSpecialTyCon tc = not $ (tyConName tc) `elemNameSet` vectSpecialTyConNames
  177. -- Build a map containing all vectorised type constructor. If the vectorised type
  178. -- constructor differs from the original one, then it is mapped to 'True'; if they are
  179. -- both the same, then it maps to 'False'.
  180. ; vectTyCons <- globalVectTyCons
  181. ; let vectTyConBase = mapUFM_Directly isDistinct vectTyCons -- 'True' iff tc /= V[[tc]]
  182. isDistinct u tc = u /= getUnique tc
  183. vectTyConFlavour = vectTyConBase
  184. `plusNameEnv`
  185. mkNameEnv [ (tyConName tycon, True)
  186. | (tycon, _) <- vectTyConsWithRHS ++ scalarTyConsWithRHS]
  187. `plusNameEnv`
  188. mkNameEnv [ (tyConName tycon, False) -- original representation
  189. | tycon <- scalarTyConsNoRHS]
  190. -- Split the list of 'TyCons' into the ones (1) that we must vectorise and those (2)
  191. -- that we could, but don't need to vectorise. Type constructors that are not data
  192. -- type constructors or use non-Haskell98 features are being dropped. They may not
  193. -- appear in vectorised code. (We also drop the local type constructors appearing in a
  194. -- VECTORISE SCALAR pragma or a VECTORISE pragma with an explicit right-hand side, as
  195. -- these are being handled separately. NB: Some type constructors may be marked SCALAR
  196. -- /and/ have an explicit right-hand side.)
  197. --
  198. -- Furthermore, 'par_tcs' are those type constructors (converted or not) whose
  199. -- definition, directly or indirectly, depends on parallel arrays. Finally, 'drop_tcs'
  200. -- are all type constructors that cannot be vectorised.
  201. ; parallelTyCons <- (`addListToNameSet` map (tyConName . fst) vectTyConsWithRHS) <$>
  202. globalParallelTyCons
  203. ; let maybeVectoriseTyCons = filter notVectSpecialTyCon tycons ++ impVectTyCons
  204. (conv_tcs, keep_tcs, par_tcs, drop_tcs)
  205. = classifyTyCons vectTyConFlavour parallelTyCons maybeVectoriseTyCons
  206. ; traceVt " known parallel : " $ ppr parallelTyCons
  207. ; traceVt " VECT SCALAR : " $ ppr (scalarTyConsNoRHS ++ map fst scalarTyConsWithRHS)
  208. ; traceVt " VECT [class] : " $ ppr impVectTyCons
  209. ; traceVt " VECT with rhs : " $ ppr (map fst (vectTyConsWithRHS ++ scalarTyConsWithRHS))
  210. ; traceVt " -- after classification (local and VECT [class] tycons) --" empty
  211. ; traceVt " reuse : " $ ppr keep_tcs
  212. ; traceVt " convert : " $ ppr conv_tcs
  213. -- warn the user about unvectorised type constructors
  214. ; let explanation = ptext (sLit "(They use unsupported language extensions") $$
  215. ptext (sLit "or depend on type constructors that are not vectorised)")
  216. drop_tcs_nosyn = filter (not . isSynTyCon) drop_tcs
  217. ; unless (null drop_tcs_nosyn) $
  218. emitVt "Warning: cannot vectorise these type constructors:" $
  219. pprQuotedList drop_tcs_nosyn $$ explanation
  220. ; mapM_ addParallelTyConAndCons $ par_tcs ++ map fst vectTyConsWithRHS
  221. ; let mapping =
  222. -- Type constructors that we found we don't need to vectorise and those
  223. -- declared VECTORISE SCALAR /without/ an explicit right-hand side, use the same
  224. -- representation in both unvectorised and vectorised code; they are not
  225. -- abstract.
  226. [(tycon, tycon, False) | tycon <- keep_tcs ++ scalarTyConsNoRHS]
  227. -- We do the same for type constructors declared VECTORISE SCALAR /without/
  228. -- an explicit right-hand side
  229. ++ [(tycon, vTycon, True) | (tycon, vTycon) <- vectTyConsWithRHS ++ scalarTyConsWithRHS]
  230. ; syn_tcs <- catMaybes <$> mapM defTyConDataCons mapping
  231. -- Vectorise all the data type declarations that we can and must vectorise (enter the
  232. -- type and data constructors into the vectorisation map on-the-fly.)
  233. ; new_tcs <- vectTyConDecls conv_tcs
  234. ; let dumpTc tc vTc = traceVt "---" (ppr tc <+> text "::" <+> ppr (dataConSig tc) $$
  235. ppr vTc <+> text "::" <+> ppr (dataConSig vTc))
  236. dataConSig tc | Just dc <- tyConSingleDataCon_maybe tc = dataConRepType dc
  237. | otherwise = panic "dataConSig"
  238. ; zipWithM_ dumpTc (filter isClassTyCon conv_tcs) (filter isClassTyCon new_tcs)
  239. -- We don't need new representation types for dictionary constructors. The constructors
  240. -- are always fully applied, and we don't need to lift them to arrays as a dictionary
  241. -- of a particular type always has the same value.
  242. ; let orig_tcs = filter (not . isClassTyCon) $ keep_tcs ++ conv_tcs
  243. vect_tcs = filter (not . isClassTyCon) $ keep_tcs ++ new_tcs
  244. -- Build 'PRepr' and 'PData' instance type constructors and family instances for all
  245. -- type constructors with vectorised representations.
  246. ; reprs <- mapM tyConRepr vect_tcs
  247. ; repr_fis <- zipWith3M buildPReprTyCon orig_tcs vect_tcs reprs
  248. ; pdata_fis <- zipWith3M buildPDataTyCon orig_tcs vect_tcs reprs
  249. ; pdatas_fis <- zipWith3M buildPDatasTyCon orig_tcs vect_tcs reprs
  250. ; let fam_insts = repr_fis ++ pdata_fis ++ pdatas_fis
  251. repr_axs = map famInstAxiom repr_fis
  252. pdata_tcs = famInstsRepTyCons pdata_fis
  253. pdatas_tcs = famInstsRepTyCons pdatas_fis
  254. ; updGEnv $ extendFamEnv fam_insts
  255. -- Generate workers for the vectorised data constructors, dfuns for the 'PA' instances of
  256. -- the vectorised type constructors, and associate the type constructors with their dfuns
  257. -- in the global environment. We get back the dfun bindings (which we will subsequently
  258. -- inject into the modules toplevel).
  259. ; (_, binds) <- fixV $ \ ~(dfuns, _) ->
  260. do { defTyConPAs (zipLazy vect_tcs dfuns)
  261. -- Query the 'PData' instance type constructors for type constructors that have a
  262. -- VECTORISE SCALAR type pragma without an explicit right-hand side (this is Item
  263. -- (3) of "Note [Pragmas to vectorise tycons]" above).
  264. ; pdata_scalar_tcs <- mapM pdataReprTyConExact scalarTyConsNoRHS
  265. -- Build workers for all vectorised data constructors (except abstract ones)
  266. ; sequence_ $
  267. zipWith3 vectDataConWorkers (orig_tcs ++ scalarTyConsNoRHS)
  268. (vect_tcs ++ scalarTyConsNoRHS)
  269. (pdata_tcs ++ pdata_scalar_tcs)
  270. -- Build a 'PA' dictionary for all type constructors (except abstract ones & those
  271. -- defined with an explicit right-hand side where the dictionary is user-supplied)
  272. ; dfuns <- sequence $
  273. zipWith4 buildTyConPADict
  274. vect_tcs
  275. repr_axs
  276. pdata_tcs
  277. pdatas_tcs
  278. ; binds <- takeHoisted
  279. ; return (dfuns, binds)
  280. }
  281. -- Return the vectorised variants of type constructors as well as the generated instance
  282. -- type constructors, family instances, and dfun bindings.
  283. ; return ( new_tcs ++ pdata_tcs ++ pdatas_tcs ++ syn_tcs
  284. , fam_insts, binds)
  285. }
  286. where
  287. addParallelTyConAndCons tycon
  288. = do
  289. { addGlobalParallelTyCon tycon
  290. ; mapM_ addGlobalParallelVar . concatMap dataConImplicitIds . tyConDataCons $ tycon
  291. }
  292. -- Add a mapping from the original to vectorised type constructor to the vectorisation map.
  293. -- Unless the type constructor is abstract, also mappings from the orignal's data constructors
  294. -- to the vectorised type's data constructors.
  295. --
  296. -- We have three cases: (1) original and vectorised type constructor are the same, (2) the
  297. -- name of the vectorised type constructor is canonical (as prescribed by 'mkVectTyConOcc'), or
  298. -- (3) the name is not canonical. In the third case, we additionally introduce a type synonym
  299. -- with the canonical name that is set equal to the non-canonical name (so that we find the
  300. -- right type constructor when reading vectorisation information from interface files).
  301. --
  302. defTyConDataCons (origTyCon, vectTyCon, isAbstract)
  303. = do
  304. { canonName <- mkLocalisedName mkVectTyConOcc origName
  305. ; if origName == vectName -- Case (1)
  306. || vectName == canonName -- Case (2)
  307. then do
  308. { defTyCon origTyCon vectTyCon -- T --> vT
  309. ; defDataCons -- Ci --> vCi
  310. ; return Nothing
  311. }
  312. else do -- Case (3)
  313. { let synTyCon = mkSyn canonName (mkTyConTy vectTyCon) -- type S = vT
  314. ; defTyCon origTyCon synTyCon -- T --> S
  315. ; defDataCons -- Ci --> vCi
  316. ; return $ Just synTyCon
  317. }
  318. }
  319. where
  320. origName = tyConName origTyCon
  321. vectName = tyConName vectTyCon
  322. mkSyn canonName ty = mkSynTyCon canonName (typeKind ty) [] [] (SynonymTyCon ty) NoParentTyCon
  323. defDataCons
  324. | isAbstract = return ()
  325. | otherwise
  326. = do { MASSERT(length (tyConDataCons origTyCon) == length (tyConDataCons vectTyCon))
  327. ; zipWithM_ defDataCon (tyConDataCons origTyCon) (tyConDataCons vectTyCon)
  328. }
  329. -- Helpers --------------------------------------------------------------------
  330. buildTyConPADict :: TyCon -> CoAxiom Unbranched -> TyCon -> TyCon -> VM Var
  331. buildTyConPADict vect_tc prepr_ax pdata_tc pdatas_tc
  332. = tyConRepr vect_tc >>= buildPADict vect_tc prepr_ax pdata_tc pdatas_tc
  333. -- Produce a custom-made worker for the data constructors of a vectorised data type. This includes
  334. -- all data constructors that may be used in vectorised code i.e., all data constructors of data
  335. -- types with 'VECTORISE [SCALAR] type' pragmas with an explicit right-hand side. Also adds a mapping
  336. -- from the original to vectorised worker into the vectorisation map.
  337. --
  338. -- FIXME: It's not nice that we need create a special worker after the data constructors has
  339. -- already been constructed. Also, I don't think the worker is properly added to the data
  340. -- constructor. Seems messy.
  341. vectDataConWorkers :: TyCon -> TyCon -> TyCon -> VM ()
  342. vectDataConWorkers orig_tc vect_tc arr_tc
  343. = do { traceVt "Building vectorised worker for datatype" (ppr orig_tc)
  344. ; bs <- sequence
  345. . zipWith3 def_worker (tyConDataCons orig_tc) rep_tys
  346. $ zipWith4 mk_data_con (tyConDataCons vect_tc)
  347. rep_tys
  348. (inits rep_tys)
  349. (tail $ tails rep_tys)
  350. ; mapM_ (uncurry hoistBinding) bs
  351. }
  352. where
  353. tyvars = tyConTyVars vect_tc
  354. var_tys = mkTyVarTys tyvars
  355. ty_args = map Type var_tys
  356. res_ty = mkTyConApp vect_tc var_tys
  357. cons = tyConDataCons vect_tc
  358. arity = length cons
  359. [arr_dc] = tyConDataCons arr_tc
  360. rep_tys = map dataConRepArgTys $ tyConDataCons vect_tc
  361. mk_data_con con tys pre post
  362. = do dflags <- getDynFlags
  363. liftM2 (,) (vect_data_con con)
  364. (lift_data_con tys pre post (mkDataConTag dflags con))
  365. sel_replicate len tag
  366. | arity > 1 = do
  367. rep <- builtin (selReplicate arity)
  368. return [rep `mkApps` [len, tag]]
  369. | otherwise = return []
  370. vect_data_con con = return $ mkConApp con ty_args
  371. lift_data_con tys pre_tys post_tys tag
  372. = do
  373. len <- builtin liftingContext
  374. args <- mapM (newLocalVar (fsLit "xs"))
  375. =<< mapM mkPDataType tys
  376. sel <- sel_replicate (Var len) tag
  377. pre <- mapM emptyPD (concat pre_tys)
  378. post <- mapM emptyPD (concat post_tys)
  379. return . mkLams (len : args)
  380. . wrapFamInstBody arr_tc var_tys
  381. . mkConApp arr_dc
  382. $ ty_args ++ sel ++ pre ++ map Var args ++ post
  383. def_worker data_con arg_tys mk_body
  384. = do
  385. arity <- polyArity tyvars
  386. body <- closedV
  387. . inBind orig_worker
  388. . polyAbstract tyvars $ \args ->
  389. liftM (mkLams (tyvars ++ args) . vectorised)
  390. $ buildClosures tyvars [] [] arg_tys res_ty mk_body
  391. raw_worker <- mkVectId orig_worker (exprType body)
  392. let vect_worker = raw_worker `setIdUnfolding`
  393. mkInlineUnfolding (Just arity) body
  394. defGlobalVar orig_worker vect_worker
  395. return (vect_worker, body)
  396. where
  397. orig_worker = dataConWorkId data_con