PageRenderTime 45ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/compiler/vectorise/Vectorise/Type/Classify.hs

https://github.com/crdueck/ghc
Haskell | 137 lines | 74 code | 17 blank | 46 comment | 9 complexity | bc1f7d4a9582de907fae86a1723f5fb3 MD5 | raw file
  1. -- Extract from a list of type constructors those (1) which need to be vectorised and (2) those
  2. -- that could be, but need not be vectorised (as a scalar representation is sufficient and more
  3. -- efficient). The type constructors that cannot be vectorised will be dropped.
  4. --
  5. -- A type constructor will only be vectorised if it is
  6. --
  7. -- (1) a data type constructor, with vanilla data constructors (i.e., data constructors admitted by
  8. -- Haskell 98) and
  9. -- (2) at least one of the type constructors that appears in its definition is also vectorised.
  10. --
  11. -- If (1) is met, but not (2), the type constructor may appear in vectorised code, but there is no
  12. -- need to vectorise that type constructor itself. This holds, for example, for all enumeration
  13. -- types. As '([::])' is being vectorised, any type constructor whose definition involves
  14. -- '([::])', either directly or indirectly, will be vectorised.
  15. module Vectorise.Type.Classify
  16. ( classifyTyCons
  17. )
  18. where
  19. import NameSet
  20. import UniqSet
  21. import UniqFM
  22. import DataCon
  23. import TyCon
  24. import TypeRep
  25. import Type
  26. import PrelNames
  27. import Digraph
  28. -- |From a list of type constructors, extract those that can be vectorised, returning them in two
  29. -- sets, where the first result list /must be/ vectorised and the second result list /need not be/
  30. -- vectorised. The third result list are those type constructors that we cannot convert (either
  31. -- because they use language extensions or because they dependent on type constructors for which
  32. -- no vectorised version is available).
  33. --
  34. -- NB: In order to be able to vectorise a type constructor, we require members of the depending set
  35. -- (i.e., those type constructors that the current one depends on) to be vectorised only if they
  36. -- are also parallel (i.e., appear in the second argument to the function).
  37. --
  38. -- The first argument determines the /conversion status/ of external type constructors as follows:
  39. --
  40. -- * tycons which have converted versions are mapped to 'True'
  41. -- * tycons which are not changed by vectorisation are mapped to 'False'
  42. -- * tycons which haven't been converted (because they can't or weren't vectorised) are not
  43. -- elements of the map
  44. --
  45. classifyTyCons :: UniqFM Bool -- ^type constructor vectorisation status
  46. -> NameSet -- ^tycons involving parallel arrays
  47. -> [TyCon] -- ^type constructors that need to be classified
  48. -> ( [TyCon] -- to be converted
  49. , [TyCon] -- need not be converted (but could be)
  50. , [TyCon] -- involve parallel arrays (whether converted or not)
  51. , [TyCon] -- can't be converted
  52. )
  53. classifyTyCons convStatus parTyCons tcs = classify [] [] [] [] convStatus parTyCons (tyConGroups tcs)
  54. where
  55. classify conv keep par novect _ _ [] = (conv, keep, par, novect)
  56. classify conv keep par novect cs pts ((tcs, ds) : rs)
  57. | can_convert && must_convert
  58. = classify (tcs ++ conv) keep (par ++ tcs_par) novect (cs `addListToUFM` [(tc, True) | tc <- tcs]) pts' rs
  59. | can_convert
  60. = classify conv (tcs ++ keep) (par ++ tcs_par) novect (cs `addListToUFM` [(tc, False) | tc <- tcs]) pts' rs
  61. | otherwise
  62. = classify conv keep (par ++ tcs_par) (tcs ++ novect) cs pts' rs
  63. where
  64. refs = ds `delListFromUniqSet` tcs
  65. -- the tycons that directly or indirectly depend on parallel arrays
  66. tcs_par | any ((`elemNameSet` parTyCons) . tyConName) . eltsUFM $ refs = tcs
  67. | otherwise = []
  68. pts' = pts `addListToNameSet` map tyConName tcs_par
  69. can_convert = (isNullUFM (filterUniqSet ((`elemNameSet` pts) . tyConName) (refs `minusUFM` cs))
  70. && all convertable tcs)
  71. || isShowClass tcs
  72. must_convert = foldUFM (||) False (intersectUFM_C const cs refs)
  73. && (not . isShowClass $ tcs)
  74. -- We currently admit Haskell 2011-style data and newtype declarations as well as type
  75. -- constructors representing classes.
  76. convertable tc
  77. = (isDataTyCon tc || isNewTyCon tc) && all isVanillaDataCon (tyConDataCons tc)
  78. || isClassTyCon tc
  79. -- !!!FIXME: currently we allow 'Show' in vectorised code without actually providing a
  80. -- vectorised definition (to be able to vectorise 'Num')
  81. isShowClass [tc] = tyConName tc == showClassName
  82. isShowClass _ = False
  83. -- Used to group type constructors into mutually dependent groups.
  84. --
  85. type TyConGroup = ([TyCon], UniqSet TyCon)
  86. -- Compute mutually recursive groups of tycons in topological order.
  87. --
  88. tyConGroups :: [TyCon] -> [TyConGroup]
  89. tyConGroups tcs = map mk_grp (stronglyConnCompFromEdgedVertices edges)
  90. where
  91. edges = [((tc, ds), tc, uniqSetToList ds) | tc <- tcs
  92. , let ds = tyConsOfTyCon tc]
  93. mk_grp (AcyclicSCC (tc, ds)) = ([tc], ds)
  94. mk_grp (CyclicSCC els) = (tcs, unionManyUniqSets dss)
  95. where
  96. (tcs, dss) = unzip els
  97. -- |Collect the set of TyCons used by the representation of some data type.
  98. --
  99. tyConsOfTyCon :: TyCon -> UniqSet TyCon
  100. tyConsOfTyCon = tyConsOfTypes . concatMap dataConRepArgTys . tyConDataCons
  101. -- |Collect the set of TyCons that occur in these types.
  102. --
  103. tyConsOfTypes :: [Type] -> UniqSet TyCon
  104. tyConsOfTypes = unionManyUniqSets . map tyConsOfType
  105. -- |Collect the set of TyCons that occur in this type.
  106. --
  107. tyConsOfType :: Type -> UniqSet TyCon
  108. tyConsOfType ty
  109. | Just ty' <- coreView ty = tyConsOfType ty'
  110. tyConsOfType (TyVarTy _) = emptyUniqSet
  111. tyConsOfType (TyConApp tc tys) = extend (tyConsOfTypes tys)
  112. where
  113. extend | isUnLiftedTyCon tc
  114. || isTupleTyCon tc = id
  115. | otherwise = (`addOneToUniqSet` tc)
  116. tyConsOfType (AppTy a b) = tyConsOfType a `unionUniqSets` tyConsOfType b
  117. tyConsOfType (FunTy a b) = (tyConsOfType a `unionUniqSets` tyConsOfType b)
  118. `addOneToUniqSet` funTyCon
  119. tyConsOfType (LitTy _) = emptyUniqSet
  120. tyConsOfType (ForAllTy _ ty) = tyConsOfType ty