summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
authorLuite Stegeman <stegeman@gmail.com>2021-01-27 11:48:42 +0100
committerMarge Bot <ben+marge-bot@smart-cactus.org>2021-03-20 07:49:15 -0400
commit7de3532f0317032f75b76150c5d3a6f76178be04 (patch)
treeb2d75538bde38581bbb5447889e9810f47e51a0f /compiler
parent0107f3568d060b4c979aa3740465c4f6ca4c2bba (diff)
downloadhaskell-7de3532f0317032f75b76150c5d3a6f76178be04.tar.gz
Transfer tickish things to GHC.Types.Tickish
Metric Increase: MultiLayerModules
Diffstat (limited to 'compiler')
-rw-r--r--compiler/GHC/Cmm/DebugBlock.hs2
-rw-r--r--compiler/GHC/Cmm/Node.hs2
-rw-r--r--compiler/GHC/Cmm/Parser.y3
-rw-r--r--compiler/GHC/CmmToAsm/Dwarf.hs2
-rw-r--r--compiler/GHC/CmmToAsm/PPC/CodeGen.hs2
-rw-r--r--compiler/GHC/CmmToAsm/X86/CodeGen.hs2
-rw-r--r--compiler/GHC/Core.hs325
-rw-r--r--compiler/GHC/Core/FVs.hs1
-rw-r--r--compiler/GHC/Core/Lint.hs1
-rw-r--r--compiler/GHC/Core/Map/Expr.hs1
-rw-r--r--compiler/GHC/Core/Opt/Arity.hs1
-rw-r--r--compiler/GHC/Core/Opt/CSE.hs1
-rw-r--r--compiler/GHC/Core/Opt/CallerCC.hs1
-rw-r--r--compiler/GHC/Core/Opt/ConstantFold.hs1
-rw-r--r--compiler/GHC/Core/Opt/FloatIn.hs1
-rw-r--r--compiler/GHC/Core/Opt/FloatOut.hs1
-rw-r--r--compiler/GHC/Core/Opt/OccurAnal.hs1
-rw-r--r--compiler/GHC/Core/Opt/Pipeline.hs1
-rw-r--r--compiler/GHC/Core/Opt/SetLevels.hs1
-rw-r--r--compiler/GHC/Core/Opt/Simplify.hs1
-rw-r--r--compiler/GHC/Core/Opt/Simplify/Utils.hs1
-rw-r--r--compiler/GHC/Core/Opt/SpecConstr.hs1
-rw-r--r--compiler/GHC/Core/Opt/Specialise.hs1
-rw-r--r--compiler/GHC/Core/Ppr.hs1
-rw-r--r--compiler/GHC/Core/Rules.hs1
-rw-r--r--compiler/GHC/Core/Seq.hs1
-rw-r--r--compiler/GHC/Core/SimpleOpt.hs1
-rw-r--r--compiler/GHC/Core/Stats.hs1
-rw-r--r--compiler/GHC/Core/Subst.hs1
-rw-r--r--compiler/GHC/Core/Tidy.hs1
-rw-r--r--compiler/GHC/Core/Unfold.hs1
-rw-r--r--compiler/GHC/Core/Utils.hs1
-rw-r--r--compiler/GHC/CoreToByteCode.hs1
-rw-r--r--compiler/GHC/CoreToIface.hs1
-rw-r--r--compiler/GHC/CoreToStg.hs1
-rw-r--r--compiler/GHC/CoreToStg/Prep.hs1
-rw-r--r--compiler/GHC/HsToCore/Coverage.hs2
-rw-r--r--compiler/GHC/HsToCore/Expr.hs1
-rw-r--r--compiler/GHC/HsToCore/Utils.hs1
-rw-r--r--compiler/GHC/Iface/Tidy.hs1
-rw-r--r--compiler/GHC/IfaceToCore.hs1
-rw-r--r--compiler/GHC/Stg/FVs.hs2
-rw-r--r--compiler/GHC/Stg/Syntax.hs3
-rw-r--r--compiler/GHC/StgToCmm/Bind.hs3
-rw-r--r--compiler/GHC/StgToCmm/Expr.hs1
-rw-r--r--compiler/GHC/Tc/Gen/Bind.hs2
-rw-r--r--compiler/GHC/Types/Tickish.hs372
-rw-r--r--compiler/Language/Haskell/Syntax/Binds.hs2
-rw-r--r--compiler/Language/Haskell/Syntax/Expr.hs2
-rw-r--r--compiler/ghc.cabal.in1
50 files changed, 423 insertions, 338 deletions
diff --git a/compiler/GHC/Cmm/DebugBlock.hs b/compiler/GHC/Cmm/DebugBlock.hs
index 0de3efe044..e6d1f2735e 100644
--- a/compiler/GHC/Cmm/DebugBlock.hs
+++ b/compiler/GHC/Cmm/DebugBlock.hs
@@ -39,13 +39,13 @@ import GHC.Cmm.BlockId
import GHC.Cmm.CLabel
import GHC.Cmm
import GHC.Cmm.Utils
-import GHC.Core
import GHC.Data.FastString ( nilFS, mkFastString )
import GHC.Unit.Module
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Cmm.Ppr.Expr ( pprExpr )
import GHC.Types.SrcLoc
+import GHC.Types.Tickish
import GHC.Utils.Misc ( seqList )
import GHC.Cmm.Dataflow.Block
diff --git a/compiler/GHC/Cmm/Node.hs b/compiler/GHC/Cmm/Node.hs
index 37a27fd75f..fe6eac3223 100644
--- a/compiler/GHC/Cmm/Node.hs
+++ b/compiler/GHC/Cmm/Node.hs
@@ -34,7 +34,7 @@ import GHC.Data.FastString
import GHC.Types.ForeignCall
import GHC.Utils.Outputable
import GHC.Runtime.Heap.Layout
-import GHC.Core (CmmTickish)
+import GHC.Types.Tickish (CmmTickish)
import qualified GHC.Types.Unique as U
import GHC.Cmm.Dataflow.Block
diff --git a/compiler/GHC/Cmm/Parser.y b/compiler/GHC/Cmm/Parser.y
index ceb5ba8bad..8a972b91d5 100644
--- a/compiler/GHC/Cmm/Parser.y
+++ b/compiler/GHC/Cmm/Parser.y
@@ -224,8 +224,6 @@ import GHC.StgToCmm.Ticky
import GHC.StgToCmm.Prof
import GHC.StgToCmm.Bind ( emitBlackHoleCode, emitUpdateFrame )
-import GHC.Core ( GenTickish(SourceNote) )
-
import GHC.Cmm.Opt
import GHC.Cmm.Graph
import GHC.Cmm
@@ -250,6 +248,7 @@ import GHC.Types.Literal
import GHC.Types.Unique
import GHC.Types.Unique.FM
import GHC.Types.SrcLoc
+import GHC.Types.Tickish ( GenTickish(SourceNote) )
import GHC.Driver.Session
import GHC.Driver.Ppr
import GHC.Driver.Config
diff --git a/compiler/GHC/CmmToAsm/Dwarf.hs b/compiler/GHC/CmmToAsm/Dwarf.hs
index b79397a998..9b48d25bf4 100644
--- a/compiler/GHC/CmmToAsm/Dwarf.hs
+++ b/compiler/GHC/CmmToAsm/Dwarf.hs
@@ -7,7 +7,7 @@ import GHC.Prelude
import GHC.Cmm.CLabel
import GHC.Cmm.Expr ( GlobalReg(..) )
import GHC.Settings.Config ( cProjectName, cProjectVersion )
-import GHC.Core ( CmmTickish, GenTickish(..) )
+import GHC.Types.Tickish ( CmmTickish, GenTickish(..) )
import GHC.Cmm.DebugBlock
import GHC.Unit.Module
import GHC.Utils.Outputable
diff --git a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs
index d547412935..1111917de8 100644
--- a/compiler/GHC/CmmToAsm/PPC/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/PPC/CodeGen.hs
@@ -57,7 +57,7 @@ import GHC.Cmm.Switch
import GHC.Cmm.CLabel
import GHC.Cmm.Dataflow.Block
import GHC.Cmm.Dataflow.Graph
-import GHC.Core ( GenTickish(..) )
+import GHC.Types.Tickish ( GenTickish(..) )
import GHC.Types.SrcLoc ( srcSpanFile, srcSpanStartLine, srcSpanStartCol )
-- The rest:
diff --git a/compiler/GHC/CmmToAsm/X86/CodeGen.hs b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
index 7699b0c692..878f3387fb 100644
--- a/compiler/GHC/CmmToAsm/X86/CodeGen.hs
+++ b/compiler/GHC/CmmToAsm/X86/CodeGen.hs
@@ -72,7 +72,7 @@ import GHC.Cmm.Dataflow.Collections
import GHC.Cmm.Dataflow.Graph
import GHC.Cmm.Dataflow.Label
import GHC.Cmm.CLabel
-import GHC.Core ( GenTickish(..) )
+import GHC.Types.Tickish ( GenTickish(..) )
import GHC.Types.SrcLoc ( srcSpanFile, srcSpanStartLine, srcSpanStartCol )
-- The rest:
diff --git a/compiler/GHC/Core.hs b/compiler/GHC/Core.hs
index e00986566d..2c30b6f3d4 100644
--- a/compiler/GHC/Core.hs
+++ b/compiler/GHC/Core.hs
@@ -6,11 +6,6 @@
{-# LANGUAGE CPP, DeriveDataTypeable, FlexibleContexts #-}
{-# LANGUAGE NamedFieldPuns #-}
{-# LANGUAGE BangPatterns #-}
-{-# LANGUAGE DataKinds #-}
-{-# LANGUAGE TypeFamilies #-}
-{-# LANGUAGE StandaloneDeriving #-}
-{-# LANGUAGE FlexibleInstances #-}
-
{-# OPTIONS_GHC -Wno-incomplete-uni-patterns #-}
{-# OPTIONS_GHC -Wno-incomplete-record-updates #-}
@@ -19,8 +14,6 @@
module GHC.Core (
-- * Main data types
Expr(..), Alt(..), Bind(..), AltCon(..), Arg,
- GenTickish(..), CoreTickish, StgTickish, CmmTickish, XTickishId,
- TickishScoping(..), TickishPlacement(..),
CoreProgram, CoreExpr, CoreAlt, CoreBind, CoreArg, CoreBndr,
TaggedExpr, TaggedAlt, TaggedBind, TaggedArg, TaggedBndr(..), deTagExpr,
@@ -59,12 +52,6 @@ module GHC.Core (
isValArg, isTypeArg, isCoArg, isTyCoArg, valArgCount, valBndrCount,
isRuntimeArg, isRuntimeVar,
- -- * Tick-related functions
- tickishCounts, tickishScoped, tickishScopesLike, tickishFloatable,
- tickishCanSplit, mkNoCount, mkNoScope,
- tickishIsCode, tickishPlace,
- tickishContains,
-
-- * Unfolding data types
Unfolding(..), UnfoldingGuidance(..), UnfoldingSource(..),
@@ -110,7 +97,6 @@ module GHC.Core (
import GHC.Prelude
import GHC.Platform
-import GHC.Types.CostCentre
import GHC.Types.Var.Env( InScopeSet )
import GHC.Types.Var
import GHC.Core.Type
@@ -119,11 +105,11 @@ import GHC.Types.Name
import GHC.Types.Name.Set
import GHC.Types.Name.Env( NameEnv, emptyNameEnv )
import GHC.Types.Literal
+import GHC.Types.Tickish
import GHC.Core.DataCon
import GHC.Unit.Module
import GHC.Types.Basic
import GHC.Types.Unique.Set
-import GHC.Types.SrcLoc ( RealSrcSpan, containsSpan )
import GHC.Utils.Binary
import GHC.Utils.Misc
@@ -132,8 +118,6 @@ import GHC.Utils.Panic
import GHC.Driver.Ppr
-import Language.Haskell.Syntax.Extension ( NoExtField )
-
import Data.Data hiding (TyCon)
import Data.Int
import Data.Word
@@ -941,313 +925,6 @@ type OutArg = CoreArg
type MOutCoercion = MCoercion
-{- *********************************************************************
-* *
- Ticks
-* *
-************************************************************************
--}
-
--- | Allows attaching extra information to points in expressions
-
--- | Used as a data type index for the GenTickish annotations
-data TickishPass
- = TickishCore
- | TickishStg
- | TickishCmm
-
-type family XBreakpoint (pass :: TickishPass)
-type instance XBreakpoint 'TickishCore = NoExtField
--- | Keep track of the type of breakpoints in STG, for GHCi
-type instance XBreakpoint 'TickishStg = Type
-type instance XBreakpoint 'TickishCmm = NoExtField
-
-type family XTickishId (pass :: TickishPass)
-type instance XTickishId 'TickishCore = Id
-type instance XTickishId 'TickishStg = Id
-type instance XTickishId 'TickishCmm = NoExtField
-
-type CoreTickish = GenTickish 'TickishCore
-type StgTickish = GenTickish 'TickishStg
--- | Tickish in Cmm context (annotations only)
-type CmmTickish = GenTickish 'TickishCmm
-
--- If you edit this type, you may need to update the GHC formalism
--- See Note [GHC Formalism] in GHC.Core.Lint
-data GenTickish pass =
- -- | An @{-# SCC #-}@ profiling annotation, either automatically
- -- added by the desugarer as a result of -auto-all, or added by
- -- the user.
- ProfNote {
- profNoteCC :: CostCentre, -- ^ the cost centre
- profNoteCount :: !Bool, -- ^ bump the entry count?
- profNoteScope :: !Bool -- ^ scopes over the enclosed expression
- -- (i.e. not just a tick)
- }
-
- -- | A "tick" used by HPC to track the execution of each
- -- subexpression in the original source code.
- | HpcTick {
- tickModule :: Module,
- tickId :: !Int
- }
-
- -- | A breakpoint for the GHCi debugger. This behaves like an HPC
- -- tick, but has a list of free variables which will be available
- -- for inspection in GHCi when the program stops at the breakpoint.
- --
- -- NB. we must take account of these Ids when (a) counting free variables,
- -- and (b) substituting (don't substitute for them)
- | Breakpoint
- { breakpointExt :: XBreakpoint pass
- , breakpointId :: !Int
- , breakpointFVs :: [XTickishId pass]
- -- ^ the order of this list is important:
- -- it matches the order of the lists in the
- -- appropriate entry in 'GHC.ByteCode.Types.ModBreaks'.
- --
- -- Careful about substitution! See
- -- Note [substTickish] in "GHC.Core.Subst".
- }
-
- -- | A source note.
- --
- -- Source notes are pure annotations: Their presence should neither
- -- influence compilation nor execution. The semantics are given by
- -- causality: The presence of a source note means that a local
- -- change in the referenced source code span will possibly provoke
- -- the generated code to change. On the flip-side, the functionality
- -- of annotated code *must* be invariant against changes to all
- -- source code *except* the spans referenced in the source notes
- -- (see "Causality of optimized Haskell" paper for details).
- --
- -- Therefore extending the scope of any given source note is always
- -- valid. Note that it is still undesirable though, as this reduces
- -- their usefulness for debugging and profiling. Therefore we will
- -- generally try only to make use of this property where it is
- -- necessary to enable optimizations.
- | SourceNote
- { sourceSpan :: RealSrcSpan -- ^ Source covered
- , sourceName :: String -- ^ Name for source location
- -- (uses same names as CCs)
- }
-
-deriving instance Eq (GenTickish 'TickishCore)
-deriving instance Ord (GenTickish 'TickishCore)
-deriving instance Data (GenTickish 'TickishCore)
-
-deriving instance Data (GenTickish 'TickishStg)
-
-deriving instance Eq (GenTickish 'TickishCmm)
-deriving instance Ord (GenTickish 'TickishCmm)
-deriving instance Data (GenTickish 'TickishCmm)
-
-
--- | A "counting tick" (where tickishCounts is True) is one that
--- counts evaluations in some way. We cannot discard a counting tick,
--- and the compiler should preserve the number of counting ticks as
--- far as possible.
---
--- However, we still allow the simplifier to increase or decrease
--- sharing, so in practice the actual number of ticks may vary, except
--- that we never change the value from zero to non-zero or vice versa.
-tickishCounts :: GenTickish pass -> Bool
-tickishCounts n@ProfNote{} = profNoteCount n
-tickishCounts HpcTick{} = True
-tickishCounts Breakpoint{} = True
-tickishCounts _ = False
-
-
--- | Specifies the scoping behaviour of ticks. This governs the
--- behaviour of ticks that care about the covered code and the cost
--- associated with it. Important for ticks relating to profiling.
-data TickishScoping =
- -- | No scoping: The tick does not care about what code it
- -- covers. Transformations can freely move code inside as well as
- -- outside without any additional annotation obligations
- NoScope
-
- -- | Soft scoping: We want all code that is covered to stay
- -- covered. Note that this scope type does not forbid
- -- transformations from happening, as long as all results of
- -- the transformations are still covered by this tick or a copy of
- -- it. For example
- --
- -- let x = tick<...> (let y = foo in bar) in baz
- -- ===>
- -- let x = tick<...> bar; y = tick<...> foo in baz
- --
- -- Is a valid transformation as far as "bar" and "foo" is
- -- concerned, because both still are scoped over by the tick.
- --
- -- Note though that one might object to the "let" not being
- -- covered by the tick any more. However, we are generally lax
- -- with this - constant costs don't matter too much, and given
- -- that the "let" was effectively merged we can view it as having
- -- lost its identity anyway.
- --
- -- Also note that this scoping behaviour allows floating a tick
- -- "upwards" in pretty much any situation. For example:
- --
- -- case foo of x -> tick<...> bar
- -- ==>
- -- tick<...> case foo of x -> bar
- --
- -- While this is always legal, we want to make a best effort to
- -- only make us of this where it exposes transformation
- -- opportunities.
- | SoftScope
-
- -- | Cost centre scoping: We don't want any costs to move to other
- -- cost-centre stacks. This means we not only want no code or cost
- -- to get moved out of their cost centres, but we also object to
- -- code getting associated with new cost-centre ticks - or
- -- changing the order in which they get applied.
- --
- -- A rule of thumb is that we don't want any code to gain new
- -- annotations. However, there are notable exceptions, for
- -- example:
- --
- -- let f = \y -> foo in tick<...> ... (f x) ...
- -- ==>
- -- tick<...> ... foo[x/y] ...
- --
- -- In-lining lambdas like this is always legal, because inlining a
- -- function does not change the cost-centre stack when the
- -- function is called.
- | CostCentreScope
-
- deriving (Eq)
-
--- | Returns the intended scoping rule for a Tickish
-tickishScoped :: GenTickish pass -> TickishScoping
-tickishScoped n@ProfNote{}
- | profNoteScope n = CostCentreScope
- | otherwise = NoScope
-tickishScoped HpcTick{} = NoScope
-tickishScoped Breakpoint{} = CostCentreScope
- -- Breakpoints are scoped: eventually we're going to do call
- -- stacks, but also this helps prevent the simplifier from moving
- -- breakpoints around and changing their result type (see #1531).
-tickishScoped SourceNote{} = SoftScope
-
--- | Returns whether the tick scoping rule is at least as permissive
--- as the given scoping rule.
-tickishScopesLike :: GenTickish pass -> TickishScoping -> Bool
-tickishScopesLike t scope = tickishScoped t `like` scope
- where NoScope `like` _ = True
- _ `like` NoScope = False
- SoftScope `like` _ = True
- _ `like` SoftScope = False
- CostCentreScope `like` _ = True
-
--- | Returns @True@ for ticks that can be floated upwards easily even
--- where it might change execution counts, such as:
---
--- Just (tick<...> foo)
--- ==>
--- tick<...> (Just foo)
---
--- This is a combination of @tickishSoftScope@ and
--- @tickishCounts@. Note that in principle splittable ticks can become
--- floatable using @mkNoTick@ -- even though there's currently no
--- tickish for which that is the case.
-tickishFloatable :: GenTickish pass -> Bool
-tickishFloatable t = t `tickishScopesLike` SoftScope && not (tickishCounts t)
-
--- | Returns @True@ for a tick that is both counting /and/ scoping and
--- can be split into its (tick, scope) parts using 'mkNoScope' and
--- 'mkNoTick' respectively.
-tickishCanSplit :: GenTickish pass -> Bool
-tickishCanSplit ProfNote{profNoteScope = True, profNoteCount = True}
- = True
-tickishCanSplit _ = False
-
-mkNoCount :: GenTickish pass -> GenTickish pass
-mkNoCount n | not (tickishCounts n) = n
- | not (tickishCanSplit n) = panic "mkNoCount: Cannot split!"
-mkNoCount n@ProfNote{} = n {profNoteCount = False}
-mkNoCount _ = panic "mkNoCount: Undefined split!"
-
-mkNoScope :: GenTickish pass -> GenTickish pass
-mkNoScope n | tickishScoped n == NoScope = n
- | not (tickishCanSplit n) = panic "mkNoScope: Cannot split!"
-mkNoScope n@ProfNote{} = n {profNoteScope = False}
-mkNoScope _ = panic "mkNoScope: Undefined split!"
-
--- | Return @True@ if this source annotation compiles to some backend
--- code. Without this flag, the tickish is seen as a simple annotation
--- that does not have any associated evaluation code.
---
--- What this means that we are allowed to disregard the tick if doing
--- so means that we can skip generating any code in the first place. A
--- typical example is top-level bindings:
---
--- foo = tick<...> \y -> ...
--- ==>
--- foo = \y -> tick<...> ...
---
--- Here there is just no operational difference between the first and
--- the second version. Therefore code generation should simply
--- translate the code as if it found the latter.
-tickishIsCode :: GenTickish pass -> Bool
-tickishIsCode SourceNote{} = False
-tickishIsCode _tickish = True -- all the rest for now
-
-
--- | Governs the kind of expression that the tick gets placed on when
--- annotating for example using @mkTick@. If we find that we want to
--- put a tickish on an expression ruled out here, we try to float it
--- inwards until we find a suitable expression.
-data TickishPlacement =
-
- -- | Place ticks exactly on run-time expressions. We can still
- -- move the tick through pure compile-time constructs such as
- -- other ticks, casts or type lambdas. This is the most
- -- restrictive placement rule for ticks, as all tickishs have in
- -- common that they want to track runtime processes. The only
- -- legal placement rule for counting ticks.
- PlaceRuntime
-
- -- | As @PlaceRuntime@, but we float the tick through all
- -- lambdas. This makes sense where there is little difference
- -- between annotating the lambda and annotating the lambda's code.
- | PlaceNonLam
-
- -- | In addition to floating through lambdas, cost-centre style
- -- tickishs can also be moved from constructors, non-function
- -- variables and literals. For example:
- --
- -- let x = scc<...> C (scc<...> y) (scc<...> 3) in ...
- --
- -- Neither the constructor application, the variable or the
- -- literal are likely to have any cost worth mentioning. And even
- -- if y names a thunk, the call would not care about the
- -- evaluation context. Therefore removing all annotations in the
- -- above example is safe.
- | PlaceCostCentre
-
- deriving (Eq)
-
--- | Placement behaviour we want for the ticks
-tickishPlace :: GenTickish pass -> TickishPlacement
-tickishPlace n@ProfNote{}
- | profNoteCount n = PlaceRuntime
- | otherwise = PlaceCostCentre
-tickishPlace HpcTick{} = PlaceRuntime
-tickishPlace Breakpoint{} = PlaceRuntime
-tickishPlace SourceNote{} = PlaceNonLam
-
--- | Returns whether one tick "contains" the other one, therefore
--- making the second tick redundant.
-tickishContains :: Eq (GenTickish pass)
- => GenTickish pass -> GenTickish pass -> Bool
-tickishContains (SourceNote sp1 n1) (SourceNote sp2 n2)
- = containsSpan sp1 sp2 && n1 == n2
- -- compare the String last
-tickishContains t1 t2
- = t1 == t2
-
{-
************************************************************************
* *
diff --git a/compiler/GHC/Core/FVs.hs b/compiler/GHC/Core/FVs.hs
index c1b4a49bbb..cef3dc3cbe 100644
--- a/compiler/GHC/Core/FVs.hs
+++ b/compiler/GHC/Core/FVs.hs
@@ -65,6 +65,7 @@ import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Name.Set
import GHC.Types.Name
+import GHC.Types.Tickish
import GHC.Types.Var.Set
import GHC.Types.Var
import GHC.Core.Type
diff --git a/compiler/GHC/Core/Lint.hs b/compiler/GHC/Core/Lint.hs
index f3c69defef..7edc0d7a28 100644
--- a/compiler/GHC/Core/Lint.hs
+++ b/compiler/GHC/Core/Lint.hs
@@ -53,6 +53,7 @@ import GHC.Types.Id.Info
import GHC.Core.Ppr
import GHC.Core.Coercion
import GHC.Types.SrcLoc
+import GHC.Types.Tickish
import GHC.Core.Type as Type
import GHC.Core.Multiplicity
import GHC.Core.UsageEnv
diff --git a/compiler/GHC/Core/Map/Expr.hs b/compiler/GHC/Core/Map/Expr.hs
index 04c786deec..30be6adea2 100644
--- a/compiler/GHC/Core/Map/Expr.hs
+++ b/compiler/GHC/Core/Map/Expr.hs
@@ -32,6 +32,7 @@ import GHC.Data.TrieMap
import GHC.Core.Map.Type
import GHC.Core
import GHC.Core.Type
+import GHC.Types.Tickish
import GHC.Types.Var
import GHC.Utils.Misc
diff --git a/compiler/GHC/Core/Opt/Arity.hs b/compiler/GHC/Core/Opt/Arity.hs
index 6dd1148e56..ec450ec245 100644
--- a/compiler/GHC/Core/Opt/Arity.hs
+++ b/compiler/GHC/Core/Opt/Arity.hs
@@ -58,6 +58,7 @@ import GHC.Core.Predicate ( isDictTy )
import GHC.Core.Multiplicity
import GHC.Types.Var.Set
import GHC.Types.Basic
+import GHC.Types.Tickish
import GHC.Builtin.Uniques
import GHC.Driver.Session ( DynFlags, GeneralFlag(..), gopt )
import GHC.Utils.Outputable
diff --git a/compiler/GHC/Core/Opt/CSE.hs b/compiler/GHC/Core/Opt/CSE.hs
index 9e3010ca47..4e5f511109 100644
--- a/compiler/GHC/Core/Opt/CSE.hs
+++ b/compiler/GHC/Core/Opt/CSE.hs
@@ -30,6 +30,7 @@ import GHC.Core.Type ( tyConAppArgs )
import GHC.Core
import GHC.Utils.Outputable
import GHC.Types.Basic
+import GHC.Types.Tickish
import GHC.Core.Map.Expr
import GHC.Utils.Misc ( filterOut, equalLength, debugIsOn )
import GHC.Utils.Panic
diff --git a/compiler/GHC/Core/Opt/CallerCC.hs b/compiler/GHC/Core/Opt/CallerCC.hs
index 68875dc18f..aeffe2c034 100644
--- a/compiler/GHC/Core/Opt/CallerCC.hs
+++ b/compiler/GHC/Core/Opt/CallerCC.hs
@@ -31,6 +31,7 @@ import GHC.Driver.Ppr
import GHC.Types.CostCentre
import GHC.Types.CostCentre.State
import GHC.Types.Name hiding (varName)
+import GHC.Types.Tickish
import GHC.Unit.Module.Name
import GHC.Unit.Module.ModGuts
import GHC.Types.SrcLoc
diff --git a/compiler/GHC/Core/Opt/ConstantFold.hs b/compiler/GHC/Core/Opt/ConstantFold.hs
index c463bda314..c34996b507 100644
--- a/compiler/GHC/Core/Opt/ConstantFold.hs
+++ b/compiler/GHC/Core/Opt/ConstantFold.hs
@@ -60,6 +60,7 @@ import GHC.Core.Type
import GHC.Types.Var.Set
import GHC.Types.Var.Env
import GHC.Types.Name.Occurrence ( occNameFS )
+import GHC.Types.Tickish
import GHC.Builtin.Names
import GHC.Data.Maybe ( orElse )
import GHC.Types.Name ( Name, nameOccName )
diff --git a/compiler/GHC/Core/Opt/FloatIn.hs b/compiler/GHC/Core/Opt/FloatIn.hs
index 7feea9f516..0f2eb85f73 100644
--- a/compiler/GHC/Core/Opt/FloatIn.hs
+++ b/compiler/GHC/Core/Opt/FloatIn.hs
@@ -34,6 +34,7 @@ import GHC.Core.Type
import GHC.Types.Basic ( RecFlag(..), isRec )
import GHC.Types.Id ( isOneShotBndr, idType, isJoinId, isJoinId_maybe )
+import GHC.Types.Tickish
import GHC.Types.Var
import GHC.Types.Var.Set
diff --git a/compiler/GHC/Core/Opt/FloatOut.hs b/compiler/GHC/Core/Opt/FloatOut.hs
index d0a544c020..ed6c3759c1 100644
--- a/compiler/GHC/Core/Opt/FloatOut.hs
+++ b/compiler/GHC/Core/Opt/FloatOut.hs
@@ -22,6 +22,7 @@ import GHC.Driver.Session
import GHC.Utils.Logger ( dumpIfSet_dyn, DumpFormat (..), Logger )
import GHC.Types.Id ( Id, idArity, idType, isDeadEndId,
isJoinId, isJoinId_maybe )
+import GHC.Types.Tickish
import GHC.Core.Opt.SetLevels
import GHC.Types.Unique.Supply ( UniqSupply )
import GHC.Data.Bag
diff --git a/compiler/GHC/Core/Opt/OccurAnal.hs b/compiler/GHC/Core/Opt/OccurAnal.hs
index 32853b6aff..d8796caa6e 100644
--- a/compiler/GHC/Core/Opt/OccurAnal.hs
+++ b/compiler/GHC/Core/Opt/OccurAnal.hs
@@ -33,6 +33,7 @@ import GHC.Core.Opt.Arity ( joinRhsArity )
import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Types.Basic
+import GHC.Types.Tickish
import GHC.Unit.Module( Module )
import GHC.Core.Coercion
import GHC.Core.Type
diff --git a/compiler/GHC/Core/Opt/Pipeline.hs b/compiler/GHC/Core/Opt/Pipeline.hs
index 0493ad911a..d3dcfb3263 100644
--- a/compiler/GHC/Core/Opt/Pipeline.hs
+++ b/compiler/GHC/Core/Opt/Pipeline.hs
@@ -70,6 +70,7 @@ import GHC.Types.Basic
import GHC.Types.Demand ( zapDmdEnvSig )
import GHC.Types.Var.Set
import GHC.Types.Var.Env
+import GHC.Types.Tickish
import GHC.Types.Unique.Supply ( UniqSupply )
import GHC.Types.Unique.FM
import GHC.Types.Name.Ppr
diff --git a/compiler/GHC/Core/Opt/SetLevels.hs b/compiler/GHC/Core/Opt/SetLevels.hs
index 88b1d34a9e..2ea0c8606d 100644
--- a/compiler/GHC/Core/Opt/SetLevels.hs
+++ b/compiler/GHC/Core/Opt/SetLevels.hs
@@ -108,6 +108,7 @@ import GHC.Types.Cpr ( mkCprSig, botCpr )
import GHC.Types.Name ( getOccName, mkSystemVarName )
import GHC.Types.Name.Occurrence ( occNameString )
import GHC.Types.Unique ( hasKey )
+import GHC.Types.Tickish ( tickishIsCode )
import GHC.Core.Type ( Type, splitTyConApp_maybe, tyCoVarsOfType
, mightBeUnliftedType, closeOverKindsDSet )
import GHC.Core.Multiplicity ( pattern Many )
diff --git a/compiler/GHC/Core/Opt/Simplify.hs b/compiler/GHC/Core/Opt/Simplify.hs
index 8090ddb369..c531da6050 100644
--- a/compiler/GHC/Core/Opt/Simplify.hs
+++ b/compiler/GHC/Core/Opt/Simplify.hs
@@ -59,6 +59,7 @@ import GHC.Core.Rules ( lookupRule, getRules, initRuleOpts )
import GHC.Types.Basic
import GHC.Utils.Monad ( mapAccumLM, liftIO )
import GHC.Utils.Logger
+import GHC.Types.Tickish
import GHC.Types.Var ( isTyCoVar )
import GHC.Data.Maybe ( orElse )
import Control.Monad
diff --git a/compiler/GHC/Core/Opt/Simplify/Utils.hs b/compiler/GHC/Core/Opt/Simplify/Utils.hs
index ec83c25cc4..672b0bce72 100644
--- a/compiler/GHC/Core/Opt/Simplify/Utils.hs
+++ b/compiler/GHC/Core/Opt/Simplify/Utils.hs
@@ -57,6 +57,7 @@ import GHC.Core.Unfold.Make
import GHC.Types.Name
import GHC.Types.Id
import GHC.Types.Id.Info
+import GHC.Types.Tickish
import GHC.Types.Var
import GHC.Types.Demand
import GHC.Types.Var.Set
diff --git a/compiler/GHC/Core/Opt/SpecConstr.hs b/compiler/GHC/Core/Opt/SpecConstr.hs
index 8ffe04ab25..1e00e4cc21 100644
--- a/compiler/GHC/Core/Opt/SpecConstr.hs
+++ b/compiler/GHC/Core/Opt/SpecConstr.hs
@@ -44,6 +44,7 @@ import GHC.Core.Make ( mkImpossibleExpr )
import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Name
+import GHC.Types.Tickish
import GHC.Types.Basic
import GHC.Driver.Session ( DynFlags(..), GeneralFlag( Opt_SpecConstrKeen )
, gopt, hasPprDebug )
diff --git a/compiler/GHC/Core/Opt/Specialise.hs b/compiler/GHC/Core/Opt/Specialise.hs
index c18785cee1..cab33d8de7 100644
--- a/compiler/GHC/Core/Opt/Specialise.hs
+++ b/compiler/GHC/Core/Opt/Specialise.hs
@@ -47,6 +47,7 @@ import GHC.Types.Basic
import GHC.Types.Unique.Supply
import GHC.Types.Unique.DFM
import GHC.Types.Name
+import GHC.Types.Tickish
import GHC.Types.Id.Make ( voidArgId, voidPrimId )
import GHC.Types.Var ( isLocalVar )
import GHC.Types.Var.Set
diff --git a/compiler/GHC/Core/Ppr.hs b/compiler/GHC/Core/Ppr.hs
index 04e51aacde..a55b545b0a 100644
--- a/compiler/GHC/Core/Ppr.hs
+++ b/compiler/GHC/Core/Ppr.hs
@@ -46,6 +46,7 @@ import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Data.FastString
import GHC.Types.SrcLoc ( pprUserRealSpan )
+import GHC.Types.Tickish
{-
************************************************************************
diff --git a/compiler/GHC/Core/Rules.hs b/compiler/GHC/Core/Rules.hs
index f29d700719..41cab2d201 100644
--- a/compiler/GHC/Core/Rules.hs
+++ b/compiler/GHC/Core/Rules.hs
@@ -58,6 +58,7 @@ import GHC.Types.Name ( Name, NamedThing(..), nameIsLocalOrFrom )
import GHC.Types.Name.Set
import GHC.Types.Name.Env
import GHC.Types.Unique.FM
+import GHC.Types.Tickish
import GHC.Core.Unify as Unify ( ruleMatchTyKiX )
import GHC.Types.Basic
import GHC.Driver.Session ( DynFlags, gopt, targetPlatform, homeUnitId_ )
diff --git a/compiler/GHC/Core/Seq.hs b/compiler/GHC/Core/Seq.hs
index 35a87aab9a..6dfbfef768 100644
--- a/compiler/GHC/Core/Seq.hs
+++ b/compiler/GHC/Core/Seq.hs
@@ -17,6 +17,7 @@ import GHC.Types.Id.Info
import GHC.Types.Demand( seqDemand, seqStrictSig )
import GHC.Types.Cpr( seqCprSig )
import GHC.Types.Basic( seqOccInfo )
+import GHC.Types.Tickish
import GHC.Types.Var.Set( seqDVarSet )
import GHC.Types.Var( varType, tyVarKind )
import GHC.Core.Type( seqType, isTyVar )
diff --git a/compiler/GHC/Core/SimpleOpt.hs b/compiler/GHC/Core/SimpleOpt.hs
index 519638d25d..90cd3f039e 100644
--- a/compiler/GHC/Core/SimpleOpt.hs
+++ b/compiler/GHC/Core/SimpleOpt.hs
@@ -41,6 +41,7 @@ import GHC.Types.Var.Set
import GHC.Types.Var.Env
import GHC.Core.DataCon
import GHC.Types.Demand( etaConvertStrictSig )
+import GHC.Types.Tickish
import GHC.Core.Coercion.Opt ( optCoercion, OptCoercionOpts (..) )
import GHC.Core.Type hiding ( substTy, extendTvSubst, extendCvSubst, extendTvSubstList
, isInScope, substTyVarBndr, cloneTyVarBndr )
diff --git a/compiler/GHC/Core/Stats.hs b/compiler/GHC/Core/Stats.hs
index e43e4e4471..04e6bc3274 100644
--- a/compiler/GHC/Core/Stats.hs
+++ b/compiler/GHC/Core/Stats.hs
@@ -17,6 +17,7 @@ import GHC.Types.Basic
import GHC.Core
import GHC.Utils.Outputable
import GHC.Core.Coercion
+import GHC.Types.Tickish
import GHC.Types.Var
import GHC.Core.Type(Type, typeSize)
import GHC.Types.Id (isJoinId)
diff --git a/compiler/GHC/Core/Subst.hs b/compiler/GHC/Core/Subst.hs
index 3ed3996488..520bfd5d16 100644
--- a/compiler/GHC/Core/Subst.hs
+++ b/compiler/GHC/Core/Subst.hs
@@ -60,6 +60,7 @@ import GHC.Types.Var.Env
import GHC.Types.Id
import GHC.Types.Name ( Name )
import GHC.Types.Var
+import GHC.Types.Tickish
import GHC.Types.Id.Info
import GHC.Types.Unique.Supply
import GHC.Data.Maybe
diff --git a/compiler/GHC/Core/Tidy.hs b/compiler/GHC/Core/Tidy.hs
index c88cbdc0c4..61f98e20a4 100644
--- a/compiler/GHC/Core/Tidy.hs
+++ b/compiler/GHC/Core/Tidy.hs
@@ -30,6 +30,7 @@ import GHC.Types.Unique (getUnique)
import GHC.Types.Unique.FM
import GHC.Types.Name hiding (tidyNameOcc)
import GHC.Types.SrcLoc
+import GHC.Types.Tickish
import GHC.Data.Maybe
import Data.List (mapAccumL)
diff --git a/compiler/GHC/Core/Unfold.hs b/compiler/GHC/Core/Unfold.hs
index 1bf641e12f..8fdbc1b891 100644
--- a/compiler/GHC/Core/Unfold.hs
+++ b/compiler/GHC/Core/Unfold.hs
@@ -61,6 +61,7 @@ import GHC.Utils.Misc
import GHC.Utils.Outputable
import GHC.Types.ForeignCall
import GHC.Types.Name
+import GHC.Types.Tickish
import qualified Data.ByteString as BS
import Data.List (isPrefixOf)
diff --git a/compiler/GHC/Core/Utils.hs b/compiler/GHC/Core/Utils.hs
index 5a4b6304f1..3f228f747d 100644
--- a/compiler/GHC/Core/Utils.hs
+++ b/compiler/GHC/Core/Utils.hs
@@ -83,6 +83,7 @@ import GHC.Types.Var.Env
import GHC.Types.Var.Set
import GHC.Types.Name
import GHC.Types.Literal
+import GHC.Types.Tickish
import GHC.Core.DataCon
import GHC.Builtin.PrimOps
import GHC.Types.Id
diff --git a/compiler/GHC/CoreToByteCode.hs b/compiler/GHC/CoreToByteCode.hs
index 23bb018806..dbb64d51d5 100644
--- a/compiler/GHC/CoreToByteCode.hs
+++ b/compiler/GHC/CoreToByteCode.hs
@@ -65,6 +65,7 @@ import GHC.Data.OrdList
import GHC.Data.Maybe
import GHC.Types.Var.Env
import GHC.Builtin.Names ( unsafeEqualityProofName )
+import GHC.Types.Tickish
import Data.List ( genericReplicate, genericLength, intersperse
, partition, scanl', sort, sortBy, zip4, zip6, nub )
diff --git a/compiler/GHC/CoreToIface.hs b/compiler/GHC/CoreToIface.hs
index 48729ea00c..a4587d58ee 100644
--- a/compiler/GHC/CoreToIface.hs
+++ b/compiler/GHC/CoreToIface.hs
@@ -73,6 +73,7 @@ import GHC.Utils.Misc
import GHC.Types.Var
import GHC.Types.Var.Env
import GHC.Types.Var.Set
+import GHC.Types.Tickish
import GHC.Core.TyCo.Rep
import GHC.Core.TyCo.Tidy ( tidyCo )
import GHC.Types.Demand ( isTopSig )
diff --git a/compiler/GHC/CoreToStg.hs b/compiler/GHC/CoreToStg.hs
index 298288d45b..b1397fe4e1 100644
--- a/compiler/GHC/CoreToStg.hs
+++ b/compiler/GHC/CoreToStg.hs
@@ -32,6 +32,7 @@ import GHC.Types.Id
import GHC.Types.Id.Info
import GHC.Core.DataCon
import GHC.Types.CostCentre
+import GHC.Types.Tickish
import GHC.Types.Var.Env
import GHC.Unit.Module
import GHC.Types.Name ( isExternalName, nameModule_maybe )
diff --git a/compiler/GHC/CoreToStg/Prep.hs b/compiler/GHC/CoreToStg/Prep.hs
index 02b5505d30..956175b3ad 100644
--- a/compiler/GHC/CoreToStg/Prep.hs
+++ b/compiler/GHC/CoreToStg/Prep.hs
@@ -72,6 +72,7 @@ import GHC.Types.Basic
import GHC.Types.Name ( NamedThing(..), nameSrcSpan, isInternalName )
import GHC.Types.SrcLoc ( SrcSpan(..), realSrcLocSpan, mkRealSrcLoc )
import GHC.Types.Literal
+import GHC.Types.Tickish
import GHC.Types.TyThing
import GHC.Types.CostCentre ( CostCentre, ccFromThisModule )
import GHC.Types.Unique.Supply
diff --git a/compiler/GHC/HsToCore/Coverage.hs b/compiler/GHC/HsToCore/Coverage.hs
index caeea519aa..c3df228778 100644
--- a/compiler/GHC/HsToCore/Coverage.hs
+++ b/compiler/GHC/HsToCore/Coverage.hs
@@ -27,7 +27,6 @@ import GHC.Unit
import GHC.Cmm.CLabel
import GHC.Core.Type
-import GHC.Core
import GHC.Core.TyCon
import GHC.Data.Maybe
@@ -50,6 +49,7 @@ import GHC.Types.HpcInfo
import GHC.Types.CostCentre
import GHC.Types.CostCentre.State
import GHC.Types.ForeignStubs
+import GHC.Types.Tickish
import Control.Monad
import Data.List (isSuffixOf, intersperse)
diff --git a/compiler/GHC/HsToCore/Expr.hs b/compiler/GHC/HsToCore/Expr.hs
index 1b18176051..8bcebb8a51 100644
--- a/compiler/GHC/HsToCore/Expr.hs
+++ b/compiler/GHC/HsToCore/Expr.hs
@@ -64,6 +64,7 @@ import GHC.Builtin.Names
import GHC.Types.Basic
import GHC.Data.Maybe
import GHC.Types.SrcLoc
+import GHC.Types.Tickish
import GHC.Utils.Misc
import GHC.Data.Bag
import GHC.Utils.Outputable as Outputable
diff --git a/compiler/GHC/HsToCore/Utils.hs b/compiler/GHC/HsToCore/Utils.hs
index 817c69c184..75dab7680f 100644
--- a/compiler/GHC/HsToCore/Utils.hs
+++ b/compiler/GHC/HsToCore/Utils.hs
@@ -79,6 +79,7 @@ import GHC.Types.Name( isInternalName )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Types.SrcLoc
+import GHC.Types.Tickish
import GHC.Utils.Misc
import GHC.Driver.Session
import GHC.Driver.Ppr
diff --git a/compiler/GHC/Iface/Tidy.hs b/compiler/GHC/Iface/Tidy.hs
index f4e681420c..76ad3c2a79 100644
--- a/compiler/GHC/Iface/Tidy.hs
+++ b/compiler/GHC/Iface/Tidy.hs
@@ -69,6 +69,7 @@ import GHC.Types.Name.Cache
import GHC.Types.Name.Ppr
import GHC.Types.Avail
import GHC.Types.Unique.Supply
+import GHC.Types.Tickish
import GHC.Types.TypeEnv
import GHC.Unit.Module
diff --git a/compiler/GHC/IfaceToCore.hs b/compiler/GHC/IfaceToCore.hs
index e7123a8add..ee604d8436 100644
--- a/compiler/GHC/IfaceToCore.hs
+++ b/compiler/GHC/IfaceToCore.hs
@@ -100,6 +100,7 @@ import GHC.Types.Name.Set
import GHC.Types.Id
import GHC.Types.Id.Make
import GHC.Types.Id.Info
+import GHC.Types.Tickish
import GHC.Types.TyThing
import GHC.Fingerprint
diff --git a/compiler/GHC/Stg/FVs.hs b/compiler/GHC/Stg/FVs.hs
index a3d8686507..62053001a6 100644
--- a/compiler/GHC/Stg/FVs.hs
+++ b/compiler/GHC/Stg/FVs.hs
@@ -49,7 +49,7 @@ import GHC.Prelude
import GHC.Stg.Syntax
import GHC.Types.Id
import GHC.Types.Var.Set
-import GHC.Core ( GenTickish(Breakpoint) )
+import GHC.Types.Tickish ( GenTickish(Breakpoint) )
import GHC.Utils.Misc
import Data.Maybe ( mapMaybe )
diff --git a/compiler/GHC/Stg/Syntax.hs b/compiler/GHC/Stg/Syntax.hs
index 72d6760f6f..03ba9b5549 100644
--- a/compiler/GHC/Stg/Syntax.hs
+++ b/compiler/GHC/Stg/Syntax.hs
@@ -68,7 +68,7 @@ module GHC.Stg.Syntax (
import GHC.Prelude
-import GHC.Core ( AltCon, StgTickish )
+import GHC.Core ( AltCon )
import GHC.Types.CostCentre ( CostCentreStack )
import Data.ByteString ( ByteString )
import Data.Data ( Data )
@@ -78,6 +78,7 @@ import GHC.Driver.Session
import GHC.Types.ForeignCall ( ForeignCall )
import GHC.Types.Id
import GHC.Types.Name ( isDynLinkName )
+import GHC.Types.Tickish ( StgTickish )
import GHC.Types.Var.Set
import GHC.Types.Literal ( Literal, literalType )
import GHC.Unit.Module ( Module )
diff --git a/compiler/GHC/StgToCmm/Bind.hs b/compiler/GHC/StgToCmm/Bind.hs
index c4d2174d13..f1346d2846 100644
--- a/compiler/GHC/StgToCmm/Bind.hs
+++ b/compiler/GHC/StgToCmm/Bind.hs
@@ -32,7 +32,7 @@ import GHC.StgToCmm.Closure
import GHC.StgToCmm.Foreign (emitPrimCall)
import GHC.Cmm.Graph
-import GHC.Core ( AltCon(..), tickishIsCode )
+import GHC.Core ( AltCon(..) )
import GHC.Cmm.BlockId
import GHC.Runtime.Heap.Layout
import GHC.Cmm
@@ -49,6 +49,7 @@ import GHC.Data.List.SetOps
import GHC.Utils.Misc
import GHC.Types.Var.Set
import GHC.Types.Basic
+import GHC.Types.Tickish ( tickishIsCode )
import GHC.Utils.Outputable
import GHC.Utils.Panic
import GHC.Data.FastString
diff --git a/compiler/GHC/StgToCmm/Expr.hs b/compiler/GHC/StgToCmm/Expr.hs
index 8047571d9f..1b57fc3813 100644
--- a/compiler/GHC/StgToCmm/Expr.hs
+++ b/compiler/GHC/StgToCmm/Expr.hs
@@ -46,6 +46,7 @@ import GHC.Core.TyCon
import GHC.Core.Type ( isUnliftedType )
import GHC.Types.RepType ( isVoidTy, countConRepArgs )
import GHC.Types.CostCentre ( CostCentreStack, currentCCS )
+import GHC.Types.Tickish
import GHC.Data.Maybe
import GHC.Utils.Misc
import GHC.Data.FastString
diff --git a/compiler/GHC/Tc/Gen/Bind.hs b/compiler/GHC/Tc/Gen/Bind.hs
index 394b4b9c31..27572b2a65 100644
--- a/compiler/GHC/Tc/Gen/Bind.hs
+++ b/compiler/GHC/Tc/Gen/Bind.hs
@@ -28,7 +28,7 @@ import {-# SOURCE #-} GHC.Tc.Gen.Match ( tcGRHSsPat, tcMatchesFun )
import {-# SOURCE #-} GHC.Tc.Gen.Expr ( tcCheckMonoExpr )
import {-# SOURCE #-} GHC.Tc.TyCl.PatSyn ( tcPatSynDecl, tcPatSynBuilderBind )
-import GHC.Core (CoreTickish, GenTickish (..))
+import GHC.Types.Tickish (CoreTickish, GenTickish (..))
import GHC.Types.CostCentre (mkUserCC, CCFlavour(DeclCC))
import GHC.Driver.Session
import GHC.Data.FastString
diff --git a/compiler/GHC/Types/Tickish.hs b/compiler/GHC/Types/Tickish.hs
new file mode 100644
index 0000000000..b7d28c01d8
--- /dev/null
+++ b/compiler/GHC/Types/Tickish.hs
@@ -0,0 +1,372 @@
+{-# LANGUAGE DataKinds #-}
+{-# LANGUAGE DeriveDataTypeable #-}
+{-# LANGUAGE TypeFamilies #-}
+{-# LANGUAGE StandaloneDeriving #-}
+{-# LANGUAGE FlexibleContexts #-}
+{-# LANGUAGE FlexibleInstances #-}
+
+module GHC.Types.Tickish (
+ GenTickish(..),
+ CoreTickish, StgTickish, CmmTickish,
+ XTickishId,
+ tickishCounts,
+ TickishScoping(..),
+ tickishScoped,
+ tickishScopesLike,
+ tickishFloatable,
+ tickishCanSplit,
+ mkNoCount,
+ mkNoScope,
+ tickishIsCode,
+ TickishPlacement(..),
+ tickishPlace,
+ tickishContains
+) where
+
+import GHC.Prelude
+
+import GHC.Core.Type
+
+import GHC.Unit.Module
+
+import GHC.Types.CostCentre
+import GHC.Types.SrcLoc ( RealSrcSpan, containsSpan )
+import GHC.Types.Var
+
+import GHC.Utils.Panic
+
+import Language.Haskell.Syntax.Extension ( NoExtField )
+
+import Data.Data
+
+{- *********************************************************************
+* *
+ Ticks
+* *
+************************************************************************
+-}
+
+-- | Allows attaching extra information to points in expressions
+
+{- | Used as a data type index for the GenTickish annotations.
+ See Note [Tickish passes]
+ -}
+data TickishPass
+ = TickishPassCore
+ | TickishPassStg
+ | TickishPassCmm
+
+{-
+ Note [Tickish passes]
+
+ Tickish annotations store different information depending on
+ where they are used. Here's a summary of the differences
+ between the passes.
+
+ - CoreTickish: Haskell and Core
+ The tickish annotations store the free variables of
+ breakpoints.
+
+ - StgTickish: Stg
+ The GHCi bytecode generator (GHC.StgToByteCode) needs
+ to know the type of each breakpoint in addition to its
+ free variables. Since we cannot compute the type from
+ an STG expression, the tickish annotations store the
+ type of breakpoints in addition to the free variables.
+
+ - CmmTickish: Cmm
+ Breakpoints are unsupported and no free variables or
+ type are stored.
+ -}
+
+type family XBreakpoint (pass :: TickishPass)
+type instance XBreakpoint 'TickishPassCore = NoExtField
+-- | Keep track of the type of breakpoints in STG, for GHCi
+type instance XBreakpoint 'TickishPassStg = Type
+type instance XBreakpoint 'TickishPassCmm = NoExtField
+
+type family XTickishId (pass :: TickishPass)
+type instance XTickishId 'TickishPassCore = Id
+type instance XTickishId 'TickishPassStg = Id
+type instance XTickishId 'TickishPassCmm = NoExtField
+
+type CoreTickish = GenTickish 'TickishPassCore
+type StgTickish = GenTickish 'TickishPassStg
+-- | Tickish in Cmm context (annotations only)
+type CmmTickish = GenTickish 'TickishPassCmm
+
+-- If you edit this type, you may need to update the GHC formalism
+-- See Note [GHC Formalism] in GHC.Core.Lint
+data GenTickish pass =
+ -- | An @{-# SCC #-}@ profiling annotation, either automatically
+ -- added by the desugarer as a result of -auto-all, or added by
+ -- the user.
+ ProfNote {
+ profNoteCC :: CostCentre, -- ^ the cost centre
+ profNoteCount :: !Bool, -- ^ bump the entry count?
+ profNoteScope :: !Bool -- ^ scopes over the enclosed expression
+ -- (i.e. not just a tick)
+ }
+
+ -- | A "tick" used by HPC to track the execution of each
+ -- subexpression in the original source code.
+ | HpcTick {
+ tickModule :: Module,
+ tickId :: !Int
+ }
+
+ -- | A breakpoint for the GHCi debugger. This behaves like an HPC
+ -- tick, but has a list of free variables which will be available
+ -- for inspection in GHCi when the program stops at the breakpoint.
+ --
+ -- NB. we must take account of these Ids when (a) counting free variables,
+ -- and (b) substituting (don't substitute for them)
+ | Breakpoint
+ { breakpointExt :: XBreakpoint pass
+ , breakpointId :: !Int
+ , breakpointFVs :: [XTickishId pass]
+ -- ^ the order of this list is important:
+ -- it matches the order of the lists in the
+ -- appropriate entry in 'GHC.ByteCode.Types.ModBreaks'.
+ --
+ -- Careful about substitution! See
+ -- Note [substTickish] in "GHC.Core.Subst".
+ }
+
+ -- | A source note.
+ --
+ -- Source notes are pure annotations: Their presence should neither
+ -- influence compilation nor execution. The semantics are given by
+ -- causality: The presence of a source note means that a local
+ -- change in the referenced source code span will possibly provoke
+ -- the generated code to change. On the flip-side, the functionality
+ -- of annotated code *must* be invariant against changes to all
+ -- source code *except* the spans referenced in the source notes
+ -- (see "Causality of optimized Haskell" paper for details).
+ --
+ -- Therefore extending the scope of any given source note is always
+ -- valid. Note that it is still undesirable though, as this reduces
+ -- their usefulness for debugging and profiling. Therefore we will
+ -- generally try only to make use of this property where it is
+ -- necessary to enable optimizations.
+ | SourceNote
+ { sourceSpan :: RealSrcSpan -- ^ Source covered
+ , sourceName :: String -- ^ Name for source location
+ -- (uses same names as CCs)
+ }
+
+deriving instance Eq (GenTickish 'TickishPassCore)
+deriving instance Ord (GenTickish 'TickishPassCore)
+deriving instance Data (GenTickish 'TickishPassCore)
+
+deriving instance Data (GenTickish 'TickishPassStg)
+
+deriving instance Eq (GenTickish 'TickishPassCmm)
+deriving instance Ord (GenTickish 'TickishPassCmm)
+deriving instance Data (GenTickish 'TickishPassCmm)
+
+
+-- | A "counting tick" (where tickishCounts is True) is one that
+-- counts evaluations in some way. We cannot discard a counting tick,
+-- and the compiler should preserve the number of counting ticks as
+-- far as possible.
+--
+-- However, we still allow the simplifier to increase or decrease
+-- sharing, so in practice the actual number of ticks may vary, except
+-- that we never change the value from zero to non-zero or vice versa.
+tickishCounts :: GenTickish pass -> Bool
+tickishCounts n@ProfNote{} = profNoteCount n
+tickishCounts HpcTick{} = True
+tickishCounts Breakpoint{} = True
+tickishCounts _ = False
+
+
+-- | Specifies the scoping behaviour of ticks. This governs the
+-- behaviour of ticks that care about the covered code and the cost
+-- associated with it. Important for ticks relating to profiling.
+data TickishScoping =
+ -- | No scoping: The tick does not care about what code it
+ -- covers. Transformations can freely move code inside as well as
+ -- outside without any additional annotation obligations
+ NoScope
+
+ -- | Soft scoping: We want all code that is covered to stay
+ -- covered. Note that this scope type does not forbid
+ -- transformations from happening, as long as all results of
+ -- the transformations are still covered by this tick or a copy of
+ -- it. For example
+ --
+ -- let x = tick<...> (let y = foo in bar) in baz
+ -- ===>
+ -- let x = tick<...> bar; y = tick<...> foo in baz
+ --
+ -- Is a valid transformation as far as "bar" and "foo" is
+ -- concerned, because both still are scoped over by the tick.
+ --
+ -- Note though that one might object to the "let" not being
+ -- covered by the tick any more. However, we are generally lax
+ -- with this - constant costs don't matter too much, and given
+ -- that the "let" was effectively merged we can view it as having
+ -- lost its identity anyway.
+ --
+ -- Also note that this scoping behaviour allows floating a tick
+ -- "upwards" in pretty much any situation. For example:
+ --
+ -- case foo of x -> tick<...> bar
+ -- ==>
+ -- tick<...> case foo of x -> bar
+ --
+ -- While this is always legal, we want to make a best effort to
+ -- only make us of this where it exposes transformation
+ -- opportunities.
+ | SoftScope
+
+ -- | Cost centre scoping: We don't want any costs to move to other
+ -- cost-centre stacks. This means we not only want no code or cost
+ -- to get moved out of their cost centres, but we also object to
+ -- code getting associated with new cost-centre ticks - or
+ -- changing the order in which they get applied.
+ --
+ -- A rule of thumb is that we don't want any code to gain new
+ -- annotations. However, there are notable exceptions, for
+ -- example:
+ --
+ -- let f = \y -> foo in tick<...> ... (f x) ...
+ -- ==>
+ -- tick<...> ... foo[x/y] ...
+ --
+ -- In-lining lambdas like this is always legal, because inlining a
+ -- function does not change the cost-centre stack when the
+ -- function is called.
+ | CostCentreScope
+
+ deriving (Eq)
+
+-- | Returns the intended scoping rule for a Tickish
+tickishScoped :: GenTickish pass -> TickishScoping
+tickishScoped n@ProfNote{}
+ | profNoteScope n = CostCentreScope
+ | otherwise = NoScope
+tickishScoped HpcTick{} = NoScope
+tickishScoped Breakpoint{} = CostCentreScope
+ -- Breakpoints are scoped: eventually we're going to do call
+ -- stacks, but also this helps prevent the simplifier from moving
+ -- breakpoints around and changing their result type (see #1531).
+tickishScoped SourceNote{} = SoftScope
+
+-- | Returns whether the tick scoping rule is at least as permissive
+-- as the given scoping rule.
+tickishScopesLike :: GenTickish pass -> TickishScoping -> Bool
+tickishScopesLike t scope = tickishScoped t `like` scope
+ where NoScope `like` _ = True
+ _ `like` NoScope = False
+ SoftScope `like` _ = True
+ _ `like` SoftScope = False
+ CostCentreScope `like` _ = True
+
+-- | Returns @True@ for ticks that can be floated upwards easily even
+-- where it might change execution counts, such as:
+--
+-- Just (tick<...> foo)
+-- ==>
+-- tick<...> (Just foo)
+--
+-- This is a combination of @tickishSoftScope@ and
+-- @tickishCounts@. Note that in principle splittable ticks can become
+-- floatable using @mkNoTick@ -- even though there's currently no
+-- tickish for which that is the case.
+tickishFloatable :: GenTickish pass -> Bool
+tickishFloatable t = t `tickishScopesLike` SoftScope && not (tickishCounts t)
+
+-- | Returns @True@ for a tick that is both counting /and/ scoping and
+-- can be split into its (tick, scope) parts using 'mkNoScope' and
+-- 'mkNoTick' respectively.
+tickishCanSplit :: GenTickish pass -> Bool
+tickishCanSplit ProfNote{profNoteScope = True, profNoteCount = True}
+ = True
+tickishCanSplit _ = False
+
+mkNoCount :: GenTickish pass -> GenTickish pass
+mkNoCount n | not (tickishCounts n) = n
+ | not (tickishCanSplit n) = panic "mkNoCount: Cannot split!"
+mkNoCount n@ProfNote{} = n {profNoteCount = False}
+mkNoCount _ = panic "mkNoCount: Undefined split!"
+
+mkNoScope :: GenTickish pass -> GenTickish pass
+mkNoScope n | tickishScoped n == NoScope = n
+ | not (tickishCanSplit n) = panic "mkNoScope: Cannot split!"
+mkNoScope n@ProfNote{} = n {profNoteScope = False}
+mkNoScope _ = panic "mkNoScope: Undefined split!"
+
+-- | Return @True@ if this source annotation compiles to some backend
+-- code. Without this flag, the tickish is seen as a simple annotation
+-- that does not have any associated evaluation code.
+--
+-- What this means that we are allowed to disregard the tick if doing
+-- so means that we can skip generating any code in the first place. A
+-- typical example is top-level bindings:
+--
+-- foo = tick<...> \y -> ...
+-- ==>
+-- foo = \y -> tick<...> ...
+--
+-- Here there is just no operational difference between the first and
+-- the second version. Therefore code generation should simply
+-- translate the code as if it found the latter.
+tickishIsCode :: GenTickish pass -> Bool
+tickishIsCode SourceNote{} = False
+tickishIsCode _tickish = True -- all the rest for now
+
+
+-- | Governs the kind of expression that the tick gets placed on when
+-- annotating for example using @mkTick@. If we find that we want to
+-- put a tickish on an expression ruled out here, we try to float it
+-- inwards until we find a suitable expression.
+data TickishPlacement =
+
+ -- | Place ticks exactly on run-time expressions. We can still
+ -- move the tick through pure compile-time constructs such as
+ -- other ticks, casts or type lambdas. This is the most
+ -- restrictive placement rule for ticks, as all tickishs have in
+ -- common that they want to track runtime processes. The only
+ -- legal placement rule for counting ticks.
+ PlaceRuntime
+
+ -- | As @PlaceRuntime@, but we float the tick through all
+ -- lambdas. This makes sense where there is little difference
+ -- between annotating the lambda and annotating the lambda's code.
+ | PlaceNonLam
+
+ -- | In addition to floating through lambdas, cost-centre style
+ -- tickishs can also be moved from constructors, non-function
+ -- variables and literals. For example:
+ --
+ -- let x = scc<...> C (scc<...> y) (scc<...> 3) in ...
+ --
+ -- Neither the constructor application, the variable or the
+ -- literal are likely to have any cost worth mentioning. And even
+ -- if y names a thunk, the call would not care about the
+ -- evaluation context. Therefore removing all annotations in the
+ -- above example is safe.
+ | PlaceCostCentre
+
+ deriving (Eq)
+
+-- | Placement behaviour we want for the ticks
+tickishPlace :: GenTickish pass -> TickishPlacement
+tickishPlace n@ProfNote{}
+ | profNoteCount n = PlaceRuntime
+ | otherwise = PlaceCostCentre
+tickishPlace HpcTick{} = PlaceRuntime
+tickishPlace Breakpoint{} = PlaceRuntime
+tickishPlace SourceNote{} = PlaceNonLam
+
+-- | Returns whether one tick "contains" the other one, therefore
+-- making the second tick redundant.
+tickishContains :: Eq (GenTickish pass)
+ => GenTickish pass -> GenTickish pass -> Bool
+tickishContains (SourceNote sp1 n1) (SourceNote sp2 n2)
+ = containsSpan sp1 sp2 && n1 == n2
+ -- compare the String last
+tickishContains t1 t2
+ = t1 == t2
diff --git a/compiler/Language/Haskell/Syntax/Binds.hs b/compiler/Language/Haskell/Syntax/Binds.hs
index ebd93d3ecd..3a369fd37e 100644
--- a/compiler/Language/Haskell/Syntax/Binds.hs
+++ b/compiler/Language/Haskell/Syntax/Binds.hs
@@ -35,12 +35,12 @@ import {-# SOURCE #-} Language.Haskell.Syntax.Pat
import Language.Haskell.Syntax.Extension
import Language.Haskell.Syntax.Type
-import GHC.Core
import GHC.Tc.Types.Evidence
import GHC.Core.Type
import GHC.Types.Basic
import GHC.Types.SourceText
import GHC.Types.SrcLoc as SrcLoc
+import GHC.Types.Tickish
import GHC.Types.Var
import GHC.Types.Fixity
import GHC.Data.Bag
diff --git a/compiler/Language/Haskell/Syntax/Expr.hs b/compiler/Language/Haskell/Syntax/Expr.hs
index 5e8714faf4..15b74e4ce5 100644
--- a/compiler/Language/Haskell/Syntax/Expr.hs
+++ b/compiler/Language/Haskell/Syntax/Expr.hs
@@ -39,13 +39,13 @@ import Language.Haskell.Syntax.Binds
-- others:
import GHC.Tc.Types.Evidence
-import GHC.Core
import GHC.Core.DataCon (FieldLabelString)
import GHC.Types.Name
import GHC.Types.Basic
import GHC.Types.Fixity
import GHC.Types.SourceText
import GHC.Types.SrcLoc
+import GHC.Types.Tickish
import GHC.Core.ConLike
import GHC.Unit.Module (ModuleName)
import GHC.Utils.Outputable
diff --git a/compiler/ghc.cabal.in b/compiler/ghc.cabal.in
index a020c440e8..76d225bd57 100644
--- a/compiler/ghc.cabal.in
+++ b/compiler/ghc.cabal.in
@@ -656,6 +656,7 @@ Library
GHC.Types.SourceText
GHC.Types.SrcLoc
GHC.Types.Target
+ GHC.Types.Tickish
GHC.Types.TypeEnv
GHC.Types.TyThing
GHC.Types.Unique