summaryrefslogtreecommitdiff
path: root/compiler/GHC/Core/TyCo/Rep.hs
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/GHC/Core/TyCo/Rep.hs')
-rw-r--r--compiler/GHC/Core/TyCo/Rep.hs85
1 files changed, 18 insertions, 67 deletions
diff --git a/compiler/GHC/Core/TyCo/Rep.hs b/compiler/GHC/Core/TyCo/Rep.hs
index be7bdb3aef..0be6824b9d 100644
--- a/compiler/GHC/Core/TyCo/Rep.hs
+++ b/compiler/GHC/Core/TyCo/Rep.hs
@@ -52,7 +52,6 @@ module GHC.Core.TyCo.Rep (
mkVisFunTyMany, mkVisFunTysMany,
mkInvisFunTyMany, mkInvisFunTysMany,
mkTyConApp,
- tYPE,
-- * Functions over binders
TyCoBinder(..), TyCoVarBinder, TyBinder,
@@ -91,9 +90,8 @@ import GHC.Core.TyCon
import GHC.Core.Coercion.Axiom
-- others
-import GHC.Builtin.Names ( liftedTypeKindTyConKey, liftedRepDataConKey, manyDataConKey, tYPETyConKey )
-import {-# SOURCE #-} GHC.Builtin.Types ( liftedTypeKindTyCon, liftedTypeKind, manyDataConTy )
-import {-# SOURCE #-} GHC.Builtin.Types.Prim ( tYPETyCon )
+import GHC.Builtin.Names ( liftedTypeKindTyConKey, manyDataConKey )
+import {-# SOURCE #-} GHC.Builtin.Types ( liftedTypeKindTyCon, manyDataConTy )
import GHC.Types.Basic ( LeftOrRight(..), pickLR )
import GHC.Types.Unique ( hasKey, Uniquable(..) )
import GHC.Utils.Outputable
@@ -1011,7 +1009,7 @@ mkTyConApp tycon tys
-- The FunTyCon (->) is always a visible one
= FunTy { ft_af = VisArg, ft_mult = w, ft_arg = ty1, ft_res = ty2 }
- -- See Note [Prefer Type over TYPE 'LiftedRep]
+ -- Note [mkTyConApp and Type]
| tycon `hasKey` liftedTypeKindTyConKey
= ASSERT2( null tys, ppr tycon $$ ppr tys )
liftedTypeKindTyConApp
@@ -1020,21 +1018,21 @@ mkTyConApp tycon tys
-- avoid reboxing every time `mkTyConApp` is called.
= ASSERT2( null tys, ppr tycon $$ ppr tys )
manyDataConTy
- -- See Note [Prefer Type over TYPE 'LiftedRep].
- | tycon `hasKey` tYPETyConKey
- , [rep] <- tys
- = tYPE rep
- -- The catch-all case
| otherwise
= TyConApp tycon tys
+-- This is a single, global definition of the type `Type`
+-- Defined here so it is only allocated once.
+-- See Note [mkTyConApp and Type]
+liftedTypeKindTyConApp :: Type
+liftedTypeKindTyConApp = TyConApp liftedTypeKindTyCon []
+
{-
-Note [Prefer Type over TYPE 'LiftedRep]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-The Core of nearly any program will have numerous occurrences of
-@TYPE 'LiftedRep@ (and, equivalently, 'Type') floating about. Concretely, while
-investigating #17292 we found that these constituting a majority of TyConApp
-constructors on the heap:
+Note [mkTyConApp and Type]
+~~~~~~~~~~~~~~~~~~~~~~~~~~
+Whilst benchmarking it was observed in #17292 that GHC allocated a lot
+of `TyConApp` constructors. Upon further inspection a large number of these
+TyConApp constructors were all duplicates of `Type` applied to no arguments.
```
(From a sample of 100000 TyConApp closures)
@@ -1048,59 +1046,12 @@ constructors on the heap:
0x45e68fd - 538 - `TYPE ...`
```
-Consequently, we try hard to ensure that operations on such types are
-efficient. Specifically, we strive to
-
- a. Avoid heap allocation of such types
- b. Use a small (shallow in the tree-depth sense) representation
- for such types
-
-Goal (b) is particularly useful as it makes traversals (e.g. free variable
-traversal, substitution, and comparison) more efficient.
-Comparison in particular takes special advantage of nullary type synonym
-applications (e.g. things like @TyConApp typeTyCon []@), Note [Comparing
-nullary type synonyms] in "GHC.Core.Type".
-
-To accomplish these we use a number of tricks:
-
- 1. Instead of representing the lifted kind as
- @TyConApp tYPETyCon [liftedRepDataCon]@ we rather prefer to
- use the 'GHC.Types.Type' type synonym (represented as a nullary TyConApp).
- This serves goal (b) since there are no applied type arguments to traverse,
- e.g., during comparison.
-
- 2. We have a top-level binding to represent `TyConApp GHC.Types.Type []`
- (namely 'GHC.Builtin.Types.Prim.liftedTypeKind'), ensuring that we
- don't need to allocate such types (goal (a)).
-
- 3. To avoid allocating 'TyConApp' constructors the
- 'GHC.Builtin.Types.Prim.tYPE' function catches the lifted case and returns
- `liftedTypeKind` instead of building an application (goal (a)).
-
- 4. Similarly, 'Type.mkTyConApp' catches applications of `TYPE` and
- handles them using 'GHC.Builtin.Types.Prim.tYPE', ensuring
- that it benefits from the optimisation described above (goal (a)).
-
-Note that it's quite important that we do not define 'liftedTypeKind' in terms
-of 'mkTyConApp' since this tricks (1) and (4) would then result in a loop.
-
-See #17958.
+Therefore in `mkTyConApp` we have a special case for `Type` to ensure that
+only one `TyConApp 'Type []` closure is allocated during the course of
+compilation. In order to avoid a potentially expensive series of checks in
+`mkTyConApp` only this egregious case is special cased at the moment.
-}
--- | Given a RuntimeRep, applies TYPE to it.
--- See Note [TYPE and RuntimeRep] in GHC.Builtin.Types.Prim.
-tYPE :: Type -> Type
-tYPE (TyConApp tc [])
- -- See Note [Prefer Type of TYPE 'LiftedRep]
- | tc `hasKey` liftedRepDataConKey = liftedTypeKind -- TYPE 'LiftedRep
-tYPE rr = TyConApp tYPETyCon [rr]
-
--- This is a single, global definition of the type `Type`
--- Defined here so it is only allocated once.
--- See Note [Prefer Type over TYPE 'LiftedRep] in this module.
-liftedTypeKindTyConApp :: Type
-liftedTypeKindTyConApp = TyConApp liftedTypeKindTyCon []
-
{-
%************************************************************************
%* *