PageRenderTime 41ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

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

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