PageRenderTime 42ms CodeModel.GetById 15ms RepoModel.GetById 1ms app.codeStats 0ms

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

https://bitbucket.org/khibino/ghc-hack
Haskell | 117 lines | 62 code | 16 blank | 39 comment | 9 complexity | 4dd05411a144ee764f4551bba83c75f8 MD5 | raw file
Possible License(s): BSD-3-Clause, BSD-2-Clause, LGPL-3.0
  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. ) where
  18. import UniqSet
  19. import UniqFM
  20. import DataCon
  21. import TyCon
  22. import TypeRep
  23. import Type
  24. import PrelNames
  25. import Digraph
  26. -- |From a list of type constructors, extract those that can be vectorised, returning them in two
  27. -- sets, where the first result list /must be/ vectorised and the second result list /need not be/
  28. -- vectorised. The third result list are those type constructors that we cannot convert (either
  29. -- because they use language extensions or because they dependent on type constructors for which
  30. -- no vectorised version is available).
  31. -- The first argument determines the /conversion status/ of external type constructors as follows:
  32. --
  33. -- * tycons which have converted versions are mapped to 'True'
  34. -- * tycons which are not changed by vectorisation are mapped to 'False'
  35. -- * tycons which can't be converted are not elements of the map
  36. --
  37. classifyTyCons :: UniqFM Bool -- ^type constructor conversion status
  38. -> [TyCon] -- ^type constructors that need to be classified
  39. -> ([TyCon], [TyCon], [TyCon]) -- ^tycons to be converted & not to be converted
  40. classifyTyCons convStatus tcs = classify [] [] [] convStatus (tyConGroups tcs)
  41. where
  42. classify conv keep ignored _ [] = (conv, keep, ignored)
  43. classify conv keep ignored cs ((tcs, ds) : rs)
  44. | can_convert && must_convert
  45. = classify (tcs ++ conv) keep ignored (cs `addListToUFM` [(tc, True) | tc <- tcs]) rs
  46. | can_convert
  47. = classify conv (tcs ++ keep) ignored (cs `addListToUFM` [(tc, False) | tc <- tcs]) rs
  48. | otherwise
  49. = classify conv keep (tcs ++ ignored) cs rs
  50. where
  51. refs = ds `delListFromUniqSet` tcs
  52. can_convert = (isNullUFM (refs `minusUFM` cs) && all convertable tcs)
  53. || isShowClass tcs
  54. must_convert = foldUFM (||) False (intersectUFM_C const cs refs)
  55. && (not . isShowClass $ tcs)
  56. -- We currently admit Haskell 2011-style data and newtype declarations as well as type
  57. -- constructors representing classes.
  58. convertable tc
  59. = (isDataTyCon tc || isNewTyCon tc) && all isVanillaDataCon (tyConDataCons tc)
  60. || isClassTyCon tc
  61. -- !!!FIXME: currently we allow 'Show' in vectorised code without actually providing a
  62. -- vectorised definition (to be able to vectorise 'Num')
  63. isShowClass [tc] = tyConName tc == showClassName
  64. isShowClass _ = False
  65. -- Used to group type constructors into mutually dependent groups.
  66. --
  67. type TyConGroup = ([TyCon], UniqSet TyCon)
  68. -- Compute mutually recursive groups of tycons in topological order.
  69. --
  70. tyConGroups :: [TyCon] -> [TyConGroup]
  71. tyConGroups tcs = map mk_grp (stronglyConnCompFromEdgedVertices edges)
  72. where
  73. edges = [((tc, ds), tc, uniqSetToList ds) | tc <- tcs
  74. , let ds = tyConsOfTyCon tc]
  75. mk_grp (AcyclicSCC (tc, ds)) = ([tc], ds)
  76. mk_grp (CyclicSCC els) = (tcs, unionManyUniqSets dss)
  77. where
  78. (tcs, dss) = unzip els
  79. -- |Collect the set of TyCons used by the representation of some data type.
  80. --
  81. tyConsOfTyCon :: TyCon -> UniqSet TyCon
  82. tyConsOfTyCon = tyConsOfTypes . concatMap dataConRepArgTys . tyConDataCons
  83. -- |Collect the set of TyCons that occur in these types.
  84. --
  85. tyConsOfTypes :: [Type] -> UniqSet TyCon
  86. tyConsOfTypes = unionManyUniqSets . map tyConsOfType
  87. -- |Collect the set of TyCons that occur in this type.
  88. --
  89. tyConsOfType :: Type -> UniqSet TyCon
  90. tyConsOfType ty
  91. | Just ty' <- coreView ty = tyConsOfType ty'
  92. tyConsOfType (TyVarTy _) = emptyUniqSet
  93. tyConsOfType (TyConApp tc tys) = extend (tyConsOfTypes tys)
  94. where
  95. extend | isUnLiftedTyCon tc
  96. || isTupleTyCon tc = id
  97. | otherwise = (`addOneToUniqSet` tc)
  98. tyConsOfType (AppTy a b) = tyConsOfType a `unionUniqSets` tyConsOfType b
  99. tyConsOfType (FunTy a b) = (tyConsOfType a `unionUniqSets` tyConsOfType b)
  100. `addOneToUniqSet` funTyCon
  101. tyConsOfType (ForAllTy _ ty) = tyConsOfType ty