sheaf pushed to branch wip/T26878 at Glasgow Haskell Compiler / GHC

Commits:

9 changed files:

Changes:

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -303,101 +303,262 @@ mkCast expr co
    303 303
     *                                                                      *
    
    304 304
     ********************************************************************* -}
    
    305 305
     
    
    306
    --- | Wraps the given expression in the source annotation, dropping the
    
    307
    --- annotation if possible.
    
    306
    +-- | Wraps the given expression in a Tick, floating the tick as far into
    
    307
    +-- the AST as possible in order to try to satisfy the tick's desired placement
    
    308
    +-- properties (as per Note [Tickish placement] in GHC.Types.Tickish).
    
    309
    +--
    
    310
    +-- Prefer using 'mkTick' over explicit use of the 'Tick' constructor.
    
    311
    +--
    
    312
    +-- Also performs small on-the-fly optimisations:
    
    313
    +--
    
    314
    +--   * Eliminate unnecessary ticks by either absorbing them into existing ones
    
    315
    +--     or dropping them if that is valid (e.g. dropping profiling ticks around
    
    316
    +--     types, coercions and literals).
    
    317
    +--   * Split profiling ticks into counting/scoping parts so that the two parts
    
    318
    +--     can be placed independently into the AST.
    
    308 319
     mkTick :: CoreTickish -> CoreExpr -> CoreExpr
    
    309
    -mkTick t orig_expr = mkTick' id orig_expr
    
    320
    +mkTick t orig_expr = mkTick' orig_expr
    
    310 321
      where
    
    311 322
       -- Some ticks (cost-centres) can be split in two, with the
    
    312 323
       -- non-counting part having laxer placement properties.
    
    313
    -  canSplit = tickishCanSplit t && tickishPlace (mkNoCount t) /= tickishPlace t
    
    324
    +  -- See Note [Scoping ticks and counting ticks] in GHC.Types.Tickish.
    
    325
    +  can_split = tickishCanSplit t
    
    314 326
     
    
    315
    -  -- mkTick' handles floating of ticks *into* the expression.
    
    316
    -  mkTick' :: (CoreExpr -> CoreExpr) -- Apply before adding tick (float with)
    
    317
    -                                    -- Always a composition of (Tick t) wrappers
    
    318
    -          -> CoreExpr               -- Current expression
    
    319
    -          -> CoreExpr
    
    320
    -          -- So in the call (mkTick' rest e), the expression
    
    321
    -          --   (rest e)
    
    322
    -          -- has the same type as e
    
    323
    -          -- Returns an expression equivalent to (Tick t (rest e))
    
    324
    -  mkTick' rest expr = case expr of
    
    325
    -    -- Float ticks into unsafe coerce the same way we would do with a cast.
    
    326
    -    Case scrut bndr ty alts@[Alt ac abs _rhs]
    
    327
    -      | Just rhs <- isUnsafeEqualityCase scrut bndr alts
    
    328
    -      -> Case scrut bndr ty [Alt ac abs (mkTick' rest rhs)]
    
    329
    -
    
    330
    -    -- Cost centre ticks should never be reordered relative to each
    
    331
    -    -- other. Therefore we can stop whenever two collide.
    
    327
    +  -- mkTick' handles floating of tick `t` *into* the expression.
    
    328
    +  mkTick' :: CoreExpr -> CoreExpr
    
    329
    +  mkTick' expr = case expr of
    
    332 330
         Tick t2 e
    
    333
    -      | ProfNote{} <- t2, ProfNote{} <- t -> Tick t $ rest expr
    
    334
    -
    
    335
    -    -- Otherwise we assume that ticks of different placements float
    
    336
    -    -- through each other.
    
    337
    -      | tickishPlace t2 /= tickishPlace t -> Tick t2 $ mkTick' rest e
    
    338
    -
    
    339
    -    -- For annotations this is where we make sure to not introduce
    
    340
    -    -- redundant ticks.
    
    341
    -      | tickishContains t t2              -> mkTick' rest e  -- Drop t2
    
    342
    -      | tickishContains t2 t              -> rest e          -- Drop t
    
    343
    -      | otherwise                         -> mkTick' (rest . Tick t2) e
    
    344
    -
    
    345
    -    -- Ticks don't care about types, so we just float all ticks
    
    346
    -    -- through them. Note that it's not enough to check for these
    
    347
    -    -- cases top-level. While mkTick will never produce Core with type
    
    348
    -    -- expressions below ticks, such constructs can be the result of
    
    349
    -    -- unfoldings. We therefore make an effort to put everything into
    
    350
    -    -- the right place no matter what we start with.
    
    351
    -    Cast e co   -> mkCast (mkTick' rest e) co
    
    352
    -    Coercion co -> Tick t $ rest (Coercion co)
    
    331
    +
    
    332
    +      -- Common up ticks when possible, including profiling ticks that
    
    333
    +      -- share a cost centre and source notes that subsume one another.
    
    334
    +      | Just t' <- combineTickish_maybe t t2
    
    335
    +      -> mkTick t' e
    
    336
    +
    
    337
    +      -- Profiling ticks for different cost centres should never be reordered
    
    338
    +      -- relative to each other. Therefore, we stop whenever two collide.
    
    339
    +      | ProfNote {} <- t
    
    340
    +      , ProfNote {} <- t2
    
    341
    +      -> Tick t expr
    
    342
    +
    
    343
    +      -- Ticks of different placements float through each other, so that each
    
    344
    +      -- tick can be floated into its expected position in the AST.
    
    345
    +      -- See Note [Tickish placement] in GHC.Types.Tickish.
    
    346
    +      | tickishPlace t2 /= tickishPlace t
    
    347
    +      -> Tick t2 $ mkTick' e
    
    353 348
     
    
    354 349
         Lam x e
    
    355 350
           -- Always float through type lambdas. Even for non-type lambdas,
    
    356 351
           -- floating is allowed for all but the most strict placement rule.
    
    357 352
           | not (isRuntimeVar x) || tickishPlace t /= PlaceRuntime
    
    358
    -      -> Lam x $ mkTick' rest e
    
    353
    +      -> Lam x $ mkTick' e
    
    359 354
     
    
    360
    -      -- If it is both counting and scoped, we split the tick into its
    
    361
    -      -- two components, often allowing us to keep the counting tick on
    
    362
    -      -- the outside of the lambda and push the scoped tick inside.
    
    363
    -      -- The point of this is that the counting tick can probably be
    
    364
    -      -- floated, and the lambda may then be in a position to be
    
    365
    -      -- beta-reduced.
    
    366
    -      | canSplit
    
    367
    -      -> Tick (mkNoScope t) $ rest $ Lam x $ mkTick (mkNoCount t) e
    
    355
    +      -- Push SCCs into lambdas.
    
    356
    +      -- See (PSCC2) in Note [Pushing SCCs inwards].
    
    357
    +      | can_split
    
    358
    +      -> Tick (mkNoScope t) $ Lam x $ mkTick (mkNoCount t) e
    
    368 359
     
    
    369 360
         App f arg
    
    370
    -      -- Always float through type applications.
    
    361
    +      -- All ticks float inwards through non-runtime arguments, as per
    
    362
    +      -- Note [Tickish placement] in GHC.Types.Tickish.
    
    371 363
           | not (isRuntimeArg arg)
    
    372
    -      -> App (mkTick' rest f) arg
    
    364
    +      -> App (mkTick' f) arg
    
    373 365
     
    
    374
    -      -- We can also float through constructor applications, placement
    
    375
    -      -- permitting. Again we can split.
    
    376
    -      | isSaturatedConApp expr && (tickishPlace t==PlaceCostCentre || canSplit)
    
    366
    +      -- Push SCCs into saturated constructor applications.
    
    367
    +      -- See (PSCC3) in Note [Pushing SCCs inwards].
    
    368
    +      | isSaturatedConApp expr
    
    369
    +      , tickishPlace t == PlaceCostCentre || can_split
    
    377 370
           -> if tickishPlace t == PlaceCostCentre
    
    378
    -         then rest $ tickHNFArgs t expr
    
    379
    -         else Tick (mkNoScope t) $ rest $ tickHNFArgs (mkNoCount t) expr
    
    371
    +         then tickHNFArgs t expr
    
    372
    +         else Tick (mkNoScope t) $ tickHNFArgs (mkNoCount t) expr
    
    373
    +
    
    374
    +    -- See Note [No ticks around types or coercions]
    
    375
    +    e@(Coercion {}) -> e
    
    376
    +    e@(Type {})     -> e
    
    377
    +    -- Don't wrap static data in a tick which compiles to code,
    
    378
    +    -- as the code will never be run.
    
    379
    +    e@(Lit {}) | tickishIsCode t -> e
    
    380
    +
    
    381
    +    -- All ticks can be floated through casts, as per Note [Tickish placement].
    
    382
    +    Cast e co   -> mkCast (mkTick' e) co
    
    383
    +
    
    384
    +    -- Treat 'unsafeCoerce' as if it was a cast: float all ticks inwards.
    
    385
    +    -- See Note [Push ticks into unsafeCoerce]
    
    386
    +    Case scrut bndr ty alts@[Alt ac abs _rhs]
    
    387
    +      | Just rhs <- isUnsafeEqualityCase scrut bndr alts
    
    388
    +      -> Case scrut bndr ty [Alt ac abs (mkTick' rhs)]
    
    380 389
     
    
    381 390
         Var x
    
    382
    -      | notFunction && tickishPlace t == PlaceCostCentre
    
    383
    -      -> rest expr  -- Drop t
    
    384
    -      | notFunction && canSplit
    
    385
    -      -> Tick (mkNoScope t) $ rest expr
    
    386
    -      where
    
    387
    -        -- SCCs can be eliminated on variables provided the variable
    
    388
    -        -- is not a function.  In these cases the SCC makes no difference:
    
    389
    -        -- the cost of evaluating the variable will be attributed to its
    
    390
    -        -- definition site.  When the variable refers to a function, however,
    
    391
    -        -- an SCC annotation on the variable affects the cost-centre stack
    
    392
    -        -- when the function is called, so we must retain those.
    
    393
    -        notFunction = not (isFunTy (idType x))
    
    394
    -
    
    395
    -    Lit{}
    
    391
    +       -- Don't drop any ticks around a function
    
    392
    +      | isFunTy (idType x)
    
    393
    +      -> Tick t expr
    
    394
    +      -- Drop SCCs around non-function variables.
    
    395
    +      -- See (PSCC1) in Note [Pushing SCCs inwards].
    
    396 396
           | tickishPlace t == PlaceCostCentre
    
    397
    -      -> rest expr   -- Drop t
    
    397
    +      -> -- Drop pure SCC ticks:  scc<foo> (x :: Int) ==> x
    
    398
    +         expr
    
    399
    +      | can_split
    
    400
    +      -> -- Drop the scoping part of the tick, but keep the counting part.
    
    401
    +         Tick (mkNoScope t) expr
    
    402
    +
    
    403
    +    -- Catch-all: annotate where we stand.
    
    404
    +    -- In particular (but not only): Let, most Cases.
    
    405
    +    _other -> Tick t expr
    
    406
    +
    
    407
    +{- Note [Pushing SCCs inwards]
    
    408
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    409
    +Amongst all ticks, SCCs have the laxest placement properties (PlaceCostCentre,
    
    410
    +as described in Note [Tickish placement] GHC.Types.Tickish):
    
    411
    +
    
    412
    +  (PSCC1) SCCs around non-function variables can be eliminated.
    
    413
    +    The cost of evaluating the variable will be attributed to its definition
    
    414
    +    site, so the SCC makes no difference. Example:
    
    415
    +
    
    416
    +      scc<foo> (x :: Int)  ==>  x
    
    417
    +
    
    418
    +    NB: this is only valid when the variable is not a function. For example, in:
    
    419
    +
    
    420
    +      scc<foo> (f :: Int -> Int)
    
    421
    +
    
    422
    +    we must retain the cost centre annotation, as it affects the cost-centre
    
    423
    +    pointer when the function is called. Discarding the SCC in this case would
    
    424
    +    defeat the profiling mechanism entirely!
    
    425
    +
    
    426
    +  (PSCC2) SCCs can be pushed into lambdas.
    
    427
    +
    
    428
    +       scc<foo> (\x -> e)  ==>  \x -> scc<foo> e
    
    429
    +
    
    430
    +  (PSCC3) We can push SCCs into (saturated) constructor applications.
    
    431
    +    For example, for an arity 2 data constructor 'D':
    
    432
    +
    
    433
    +       scc<foo> (D e1 e2)  ==>  D (scc<foo> e1) (scc<foo> e2)
    
    434
    +
    
    435
    +Now, two kinds of ticks contain SCCs:
    
    436
    +
    
    437
    +  - bare SCCs (i.e. ProfNote with profNoteCounts = False, profNoteScopes = True)
    
    438
    +  - profiling ticks that both count and scope
    
    439
    +
    
    440
    +The above explanation deals with bare SCCs. When handling profiling ticks that
    
    441
    +both count and scope, we can split tick into two, so that the scoping part can
    
    442
    +be pushed inwards (or even discarded). Specifically, we perform the following
    
    443
    +transformations:
    
    444
    +
    
    445
    +  (PSCC1) Drop the SCC around non-function variables, keeping only the counting
    
    446
    +    part:
    
    447
    +
    
    448
    +       scctick<foo> (x :: Int)  ==>  tick<foo> x
    
    449
    +
    
    450
    +  (PSCC2) Push the SCC inside lambdas:
    
    451
    +
    
    452
    +       scctick<foo> (\x. e)  ==>  tick<foo> (\x. scc<foo> e)
    
    453
    +
    
    454
    +    NB: we must keep the counting part outside the lambda, in order to preserve
    
    455
    +    tick counter tallies – it would not be sound to push the counting part inside.
    
    398 456
     
    
    399
    -    -- Catch-all: Annotate where we stand
    
    400
    -    _any -> Tick t $ rest expr
    
    457
    +  (PSCC3) Push the SCC inside saturated contructor applications.
    
    458
    +
    
    459
    +       scctick<foo> (D e1 e2)  ==>  tick<foo> (D (scc<foo> e1) (scc<foo> e2))
    
    460
    +
    
    461
    +The benefit of these transformation is that the counting part, tick<foo>, can
    
    462
    +likely be floated out of the way, which may expose additional optimisation
    
    463
    +opportunities. For example, for (PSCC2):
    
    464
    +
    
    465
    +  (scctick<foo> (\x. e)) arg
    
    466
    +
    
    467
    +    ==>{PSCC2}
    
    468
    +
    
    469
    +  (tick<foo> (\x. scc<foo> e)) arg
    
    470
    +
    
    471
    +    ==>{GHC.Core.Opt.FloatOut.floatExpr, because 'tick<foo>' has no scope}
    
    472
    +
    
    473
    +  tick<foo> ((\x. scc<foo> e) arg)
    
    474
    +
    
    475
    +    ==>{beta reduction}
    
    476
    +
    
    477
    +  tick<foo> (let x = arg in scc<foo> e)
    
    478
    +
    
    479
    +For (PSCC3):
    
    480
    +
    
    481
    +  case (scctick<foo> (Just x)) of { Nothing -> 0; Just y -> y + 1 }
    
    482
    +
    
    483
    +    ==>{PSCC3}
    
    484
    +
    
    485
    +  case (tick<foo> (Just (scc<foo> x))) of { Nothing -> 0; Just y -> y + 1 }
    
    486
    +
    
    487
    +    ==>{GHC.Core.Opt.FloatOut.floatExpr, because 'tick<foo>' has no scope}
    
    488
    +
    
    489
    +  tick<foo> (case Just (scc<foo> x) of { Nothing -> 0; Just y -> y + 1 })
    
    490
    +
    
    491
    +    ==>{case of known constructor}
    
    492
    +
    
    493
    +  tick<foo> (let y = scc<foo> x in y + 1)
    
    494
    +
    
    495
    +Note [Push ticks into unsafeCoerce]
    
    496
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    497
    +In #25212, we had a program of the form:
    
    498
    +
    
    499
    +  data Box = Box Any
    
    500
    +  asBox :: a -> Box
    
    501
    +  asBox x = {-# SCC asBox #-} Box (unsafeCoerce x)
    
    502
    +
    
    503
    +As per Note [Implementing unsafeCoerce] in GHC.Internal.Unsafe.Coerce, the call
    
    504
    +to `unsafeCoerce` turns into
    
    505
    +
    
    506
    +  case unsafeEqualityProof @Type @a @Any of
    
    507
    +    UnsafeRefl (co :: a ~# Any) -> x |> Sub co
    
    508
    +
    
    509
    +The worker for 'asBox' is then of the form:
    
    510
    +
    
    511
    +  $wasBox = \@a (x :: a) ->
    
    512
    +    (# case unsafeEqualityProof @Type @a @Any of
    
    513
    +        UnsafeRefl (co :: a ~# Any) -> x |> Sub co
    
    514
    +    #)
    
    515
    +
    
    516
    +When inserting the SCC, we push it into the constructor as per (PSCC3) in
    
    517
    +Note [Pushing SCCs inwards], so we get:
    
    518
    +
    
    519
    +  $wasBox = \@a (x :: a) ->
    
    520
    +    tick<asBox>
    
    521
    +    (# scc<asBox>
    
    522
    +       case unsafeEqualityProof @Type @a @Any of
    
    523
    +         UnsafeRefl (co :: a ~# Any) -> x |> Sub co
    
    524
    +    #)
    
    525
    +
    
    526
    +Now, if we don't push the SCC tick into the case statement, Core Prep will
    
    527
    +see an expression like 'MkSolo# (scc<asBox> ...)', which it will ANFise to
    
    528
    +'let x = scc<asBox> ... in MkSolo# x', creating an unwanted thunk in the process.
    
    529
    +
    
    530
    +So the strategy is to treat this 'unsafeEqualityProof' case statement as if it
    
    531
    +was a cast. We thus push the SCC into the RHS of the pattern match:
    
    532
    +
    
    533
    +  $wasBox = \@a (x :: a) ->
    
    534
    +    tick<asBox>
    
    535
    +    (# case unsafeEqualityProof @Type @a @Any of
    
    536
    +         UnsafeRefl (co :: a ~# Any) -> scc<asBox> x |> Sub co
    
    537
    +    #)
    
    538
    +
    
    539
    +Then the SCC completely evaporates, as per (PSCC1) in Note [Pushing SCCs inwards].
    
    540
    +
    
    541
    +Note [No ticks around types or coercions]
    
    542
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    543
    +It doesn't make much sense to put a tick around a type or a coercion, as both
    
    544
    +types and coercions are erased in the end.
    
    545
    +
    
    546
    +In fact, it is quite dangerous to add a tick around types or coercions, because
    
    547
    +the optimiser does not robustly look through ticks:
    
    548
    +
    
    549
    +  - 'GHC.Core.SimpleOpt.simple_bind_pair' does not look through ticks when
    
    550
    +    looking at the RHS to decide whether it is a Type or Coercion,
    
    551
    +  - 'GHC.Core.Opt.Simplify.Iteration.completeBind' does not look through ticks
    
    552
    +    when looking at the RHS of an CoVar binding.
    
    553
    +
    
    554
    +This means it is vital to drop ticks around types/coercions:
    
    555
    +
    
    556
    +  - (#26941) Core Lint rejects bindings of the form "let co = tick ..."
    
    557
    +    in which the LHS is a CoVar and the RHS is a ticked Coercion.
    
    558
    +  - (#27121) The simplifier mis-handles ticked coercion bindings, which can
    
    559
    +    result in 'lookupIdSubst' panics (due to failing to extend the substitution
    
    560
    +    with a coercion).
    
    561
    +-}
    
    401 562
     
    
    402 563
     mkTicks :: [CoreTickish] -> CoreExpr -> CoreExpr
    
    403 564
     mkTicks ticks expr = foldr mkTick expr ticks
    
    ... ... @@ -2573,8 +2734,8 @@ exprIsTickedString = isJust . exprIsTickedString_maybe
    2573 2734
     exprIsTickedString_maybe :: CoreExpr -> Maybe ByteString
    
    2574 2735
     exprIsTickedString_maybe (Lit (LitString bs)) = Just bs
    
    2575 2736
     exprIsTickedString_maybe (Tick t e)
    
    2576
    -  -- we don't tick literals with CostCentre ticks, compare to mkTick
    
    2577
    -  | tickishPlace t == PlaceCostCentre = Nothing
    
    2737
    +  -- Shortcut: ticks with code never wrap literals (compare with 'mkTick')
    
    2738
    +  | tickishIsCode t = Nothing
    
    2578 2739
       | otherwise = exprIsTickedString_maybe e
    
    2579 2740
     exprIsTickedString_maybe _ = Nothing
    
    2580 2741
     
    

  • compiler/GHC/Types/Tickish.hs
    ... ... @@ -17,6 +17,7 @@ module GHC.Types.Tickish (
    17 17
       TickishPlacement(..),
    
    18 18
       tickishPlace,
    
    19 19
       tickishContains,
    
    20
    +  combineTickish_maybe,
    
    20 21
     
    
    21 22
       -- * Breakpoint tick identifiers
    
    22 23
       BreakpointId(..), BreakTickIndex
    
    ... ... @@ -261,8 +262,12 @@ Ticks have two independent attributes:
    261 262
     
    
    262 263
          See Note [Scoped ticks]
    
    263 264
     
    
    265
    +Note that profiling notes which both count and scope can be split into two
    
    266
    +separate ticks, one that counts and doesn't scope and one that scopes and doesn't
    
    267
    +count; see 'tickishCanSplit', 'mkNoCount' and 'mkNoScope'.
    
    268
    +
    
    264 269
     Note [Counting ticks]
    
    265
    -~~~~~~~~~~~~~~~~~~~~
    
    270
    +~~~~~~~~~~~~~~~~~~~~~
    
    266 271
     The following ticks count:
    
    267 272
       - ProfNote ticks with profNoteCounts = True
    
    268 273
       - HPC ticks
    
    ... ... @@ -290,7 +295,7 @@ sharing, so in practice the actual number of ticks may vary, except
    290 295
     that we never change the value from zero to non-zero or vice-versa.
    
    291 296
     
    
    292 297
     Note [Scoped ticks]
    
    293
    -~~~~~~~~~~~~~~~~~~~~
    
    298
    +~~~~~~~~~~~~~~~~~~~
    
    294 299
     The following ticks are scoped:
    
    295 300
       - ProfNote ticks with profNoteScope = True
    
    296 301
       - Breakpoints
    
    ... ... @@ -375,6 +380,61 @@ Whether we are allowed to float in additional cost depends on the tick:
    375 380
     
    
    376 381
         While these transformations are legal, we want to make a best effort to
    
    377 382
         only make use of them where it exposes transformation opportunities.
    
    383
    +
    
    384
    +Note [Tickish placement]
    
    385
    +~~~~~~~~~~~~~~~~~~~~~~~~
    
    386
    +The placement behaviour of ticks (i.e. which nodes we want the tick to be placed
    
    387
    +around in the AST) is governed by 'TickishPlacement'.
    
    388
    +From most restrictive to least restrictive placement rules:
    
    389
    +
    
    390
    +  - PlaceRuntime: counting ticks.
    
    391
    +
    
    392
    +    Ticks with 'PlaceRuntime' placement want to be placed around run-time
    
    393
    +    expressions. They can be moved through pure compile-time constructs such as
    
    394
    +    other type arguments, casts, or type lambdas:
    
    395
    +
    
    396
    +      tick <t> (f @ty)    ==>   (tick <t> f) @ty
    
    397
    +      tick <t> (e |> co)  ==>   (tick <t> e) |> co
    
    398
    +      tick <t> (/\a. e)   ==>   /\a. tick <t> e
    
    399
    +
    
    400
    +    This is the most restrictive placement rule for ticks, as all tickishs have
    
    401
    +    in common that they want to track runtime behaviour.
    
    402
    +
    
    403
    +    Any tick that counts (see Note [Counting ticks]) has 'PlaceRuntime' placement.
    
    404
    +
    
    405
    +  - PlaceNonLam: source notes.
    
    406
    +
    
    407
    +    Like PlaceRuntime, but we can also float the tick through value lambdas:
    
    408
    +
    
    409
    +      tick <t> (\x. e)   ==>   \x. tick <t> e
    
    410
    +
    
    411
    +    This makes sense where there is little difference between annotating the
    
    412
    +    lambda and annotating the lambda's code.
    
    413
    +
    
    414
    +  - PlaceCostCentre: non-counting profiling ticks.
    
    415
    +
    
    416
    +    In addition to floating through lambdas, cost-centre style tickishs can be
    
    417
    +    pushed into (saturated) constructor applications, and can be eliminated when
    
    418
    +    placed around non-function variables:
    
    419
    +
    
    420
    +      tick <t> (C e1 e2)   ==>  C (tick <t> e1) (tick <t> e2)
    
    421
    +
    
    422
    +      tick <t> (x :: Int)  ==>  (x :: Int)
    
    423
    +
    
    424
    +    Neither the constructor application nor the variable 'x' are likely to have
    
    425
    +    any cost worth mentioning.
    
    426
    +
    
    427
    +We generally try to push ticks inwards until they end up placed around a Core
    
    428
    +expression that is appropriate for their placement rule, as described above.
    
    429
    +This gives us the opportunity to eliminate the tick, either by combining it with
    
    430
    +another tick (see 'combineTickish_maybe') or by dropping it altogether. For
    
    431
    +example, a (non-counting) SCC around a non-function variable can be dropped, as
    
    432
    +there is no cost to scope over.
    
    433
    +
    
    434
    +After the tick has been placed by 'mkTick', the simplifier may later (during
    
    435
    +simplification) decide to float it outwards (see e.g. GHC.Core.Opt.Simplify.Iteration.simplTick).
    
    436
    +The story here is not fully worked out, as the simplifier calls 'mkTick', which
    
    437
    +might push the tick inwards again.
    
    378 438
     -}
    
    379 439
     
    
    380 440
     -- | Returns @True@ for ticks that can be floated upwards easily even
    
    ... ... @@ -441,35 +501,19 @@ isProfTick _ = False
    441 501
     -- annotating for example using @mkTick@. If we find that we want to
    
    442 502
     -- put a tickish on an expression ruled out here, we try to float it
    
    443 503
     -- inwards until we find a suitable expression.
    
    504
    +--
    
    505
    +-- See Note [Tickish placement].
    
    444 506
     data TickishPlacement =
    
    445 507
     
    
    446
    -    -- | Place ticks exactly on run-time expressions. We can still
    
    447
    -    -- move the tick through pure compile-time constructs such as
    
    448
    -    -- other ticks, casts or type lambdas. This is the most
    
    449
    -    -- restrictive placement rule for ticks, as all tickishs have in
    
    450
    -    -- common that they want to track runtime processes. The only
    
    451
    -    -- legal placement rule for counting ticks.
    
    452
    -    -- NB: We generally try to move these as close to the relevant
    
    453
    -    -- runtime expression as possible. This means they get pushed through
    
    454
    -    -- tyoe arguments. E.g. we create `(tick f) @Bool` instead of `tick (f @Bool)`.
    
    508
    +    -- | Place ticks exactly on run-time expressions, moving them through pure
    
    509
    +    -- compile-time constructs such as other ticks, casts or type lambdas.
    
    455 510
         PlaceRuntime
    
    456 511
     
    
    457
    -    -- | As @PlaceRuntime@, but we float the tick through all
    
    458
    -    -- lambdas. This makes sense where there is little difference
    
    459
    -    -- between annotating the lambda and annotating the lambda's code.
    
    512
    +    -- | As @PlaceRuntime@, but also allow to float the tick through all lambdas.
    
    460 513
       | PlaceNonLam
    
    461 514
     
    
    462
    -    -- | In addition to floating through lambdas, cost-centre style
    
    463
    -    -- tickishs can also be moved from constructors, non-function
    
    464
    -    -- variables and literals. For example:
    
    465
    -    --
    
    466
    -    --   let x = scc<...> C (scc<...> y) (scc<...> 3) in ...
    
    467
    -    --
    
    468
    -    -- Neither the constructor application, the variable or the
    
    469
    -    -- literal are likely to have any cost worth mentioning. And even
    
    470
    -    -- if y names a thunk, the call would not care about the
    
    471
    -    -- evaluation context. Therefore removing all annotations in the
    
    472
    -    -- above example is safe.
    
    515
    +    -- | As 'PlaceNonLam', but also float through constructors, non-function
    
    516
    +    -- variables and literals.
    
    473 517
       | PlaceCostCentre
    
    474 518
     
    
    475 519
       deriving (Eq,Show)
    
    ... ... @@ -477,7 +521,9 @@ data TickishPlacement =
    477 521
     instance Outputable TickishPlacement where
    
    478 522
       ppr = text . show
    
    479 523
     
    
    480
    --- | Placement behaviour we want for the ticks
    
    524
    +-- | Placement behaviour we want for the ticks.
    
    525
    +--
    
    526
    +-- See Note [Tickish placement].
    
    481 527
     tickishPlace :: GenTickish pass -> TickishPlacement
    
    482 528
     tickishPlace n@ProfNote{}
    
    483 529
       | profNoteCount n        = PlaceRuntime
    
    ... ... @@ -486,6 +532,43 @@ tickishPlace HpcTick{} = PlaceRuntime
    486 532
     tickishPlace Breakpoint{}  = PlaceRuntime
    
    487 533
     tickishPlace SourceNote{}  = PlaceNonLam
    
    488 534
     
    
    535
    +-- | Merge two ticks into one, if that is possible.
    
    536
    +--
    
    537
    +-- Examples:
    
    538
    +--
    
    539
    +--  - combine two source note ticks if one contains the other,
    
    540
    +--  - combine a non-counting profiling tick with a non-scoping profiling tick
    
    541
    +--    for the same cost centre
    
    542
    +--  - combine two equal breakpoint ticks or HPC ticks
    
    543
    +combineTickish_maybe :: Eq (GenTickish pass)
    
    544
    +                     => GenTickish pass -> GenTickish pass -> Maybe (GenTickish pass)
    
    545
    +combineTickish_maybe
    
    546
    +  (ProfNote { profNoteCC = cc1, profNoteCount = cnt1, profNoteScope = scope1 })
    
    547
    +  (ProfNote { profNoteCC = cc2, profNoteCount = cnt2, profNoteScope = scope2 })
    
    548
    +    | cc1 == cc2
    
    549
    +    , not cnt1 || not cnt2
    
    550
    +    = Just $ ProfNote { profNoteCC    = cc1
    
    551
    +                      , profNoteCount = cnt1 || cnt2
    
    552
    +                      , profNoteScope = scope1 || scope2
    
    553
    +                      }
    
    554
    +combineTickish_maybe t1@(SourceNote sp1 n1) t2@(SourceNote sp2 n2)
    
    555
    +  | n1 == n2
    
    556
    +  , sp1 `containsSpan` sp2
    
    557
    +  = Just t1
    
    558
    +  | n1 == n2
    
    559
    +  , sp2 `containsSpan` sp1
    
    560
    +  = Just t2
    
    561
    +  -- NB: it would be possible to use 'combineRealSrcSpans' instead,
    
    562
    +  -- but that has the risk of combining many source note ticks into a single
    
    563
    +  -- tick with a huge source span.
    
    564
    +combineTickish_maybe t1@(HpcTick {}) t2@(HpcTick {})
    
    565
    +  | t1 == t2
    
    566
    +  = Just t1
    
    567
    +combineTickish_maybe t1@(Breakpoint {}) t2@(Breakpoint {})
    
    568
    +  | t1 == t2
    
    569
    +  = Just t1
    
    570
    +combineTickish_maybe _ _ = Nothing
    
    571
    +
    
    489 572
     -- | Returns whether one tick "contains" the other one, therefore
    
    490 573
     -- making the second tick redundant.
    
    491 574
     tickishContains :: Eq (GenTickish pass)
    

  • libraries/ghc-heap/tests/tso_and_stack_closures.hs
    ... ... @@ -48,7 +48,9 @@ main = do
    48 48
                             assertEqual (cc_module myCostCentre) "Main"
    
    49 49
                             assertEqual (cc_srcloc myCostCentre) (Just "tso_and_stack_closures.hs:24:48-80")
    
    50 50
                             assertEqual (cc_is_caf myCostCentre) False
    
    51
    -                    Nothing -> error $ "MyCostCentre not found in:\n" ++ unlines (cc_label <$> linkedCostCentres costCentre)
    
    51
    +                    Nothing -> error "MyCostCentre not found"
    
    52
    +                      -- Don't print all of 'linkedCostCentres costCentre',
    
    53
    +                      -- as that is ~20k lines of output.
    
    52 54
     #endif
    
    53 55
     
    
    54 56
     linkedCostCentres :: Maybe CostCentre -> [CostCentre]
    

  • testsuite/tests/profiling/should_compile/T27121.hs
    1
    +module T27121 where
    
    2
    +
    
    3
    +import T27121_aux
    
    4
    +
    
    5
    +updateFileDiagnostics
    
    6
    +  :: LanguageContextEnv ()
    
    7
    +  -> IO ()
    
    8
    +updateFileDiagnostics env = do
    
    9
    +  withTrace $ \ _tag ->
    
    10
    +    runLspT env $ do
    
    11
    +      sendNotification SMethod_TextDocumentPublishDiagnostics
    
    12
    +        PublishDiagnosticsParams

  • testsuite/tests/profiling/should_compile/T27121_aux.hs
    1
    +{-# LANGUAGE DataKinds #-}
    
    2
    +{-# LANGUAGE DerivingStrategies #-}
    
    3
    +{-# LANGUAGE DuplicateRecordFields #-}
    
    4
    +{-# LANGUAGE FunctionalDependencies #-}
    
    5
    +{-# LANGUAGE LambdaCase #-}
    
    6
    +{-# LANGUAGE RoleAnnotations #-}
    
    7
    +{-# LANGUAGE TypeFamilies #-}
    
    8
    +
    
    9
    +module T27121_aux
    
    10
    +  ( withTrace
    
    11
    +  , sendNotification
    
    12
    +  , LspT, runLspT
    
    13
    +  , SMethod(..)
    
    14
    +  , LanguageContextEnv
    
    15
    +  , PublishDiagnosticsParams(..)
    
    16
    +  )
    
    17
    + where
    
    18
    +
    
    19
    +-- base
    
    20
    +import Control.Monad.IO.Class ( MonadIO, liftIO )
    
    21
    +import Data.Kind ( Type )
    
    22
    +import GHC.TypeLits ( Symbol )
    
    23
    +
    
    24
    +--------------------------------------------------------------------------------
    
    25
    +
    
    26
    +withTrace :: Monad m => ((String -> String -> m ()) -> m a) -> m a
    
    27
    +withTrace act
    
    28
    +  | myUserTracingEnabled
    
    29
    +  = return undefined
    
    30
    +  | otherwise = act (\_ _ -> pure ())
    
    31
    +{-# NOINLINE withTrace #-}
    
    32
    +
    
    33
    +myUserTracingEnabled :: Bool
    
    34
    +myUserTracingEnabled = False
    
    35
    +{-# NOINLINE myUserTracingEnabled #-}
    
    36
    +
    
    37
    +type Text = String
    
    38
    +
    
    39
    +newtype LspT config a = LspT {unLspT :: LanguageContextEnv config -> IO a}
    
    40
    +
    
    41
    +instance Functor (LspT config) where
    
    42
    +  fmap f (LspT g) = LspT (fmap f . g)
    
    43
    +
    
    44
    +instance Applicative (LspT config) where
    
    45
    +  pure = LspT . const . pure
    
    46
    +  LspT f <*> LspT a = LspT $ \ env -> f env <*> a env
    
    47
    +instance Monad (LspT config) where
    
    48
    +  LspT a >>= f = LspT $ \ env -> do
    
    49
    +    b <- a env
    
    50
    +    unLspT ( f b ) env
    
    51
    +instance MonadIO (LspT config) where
    
    52
    +  liftIO = LspT . const . liftIO
    
    53
    +
    
    54
    +type role LspT representational nominal
    
    55
    +
    
    56
    +runLspT :: LanguageContextEnv config -> LspT config a -> IO a
    
    57
    +runLspT env (LspT f) = f env
    
    58
    +{-# INLINE runLspT #-}
    
    59
    +
    
    60
    +data PublishDiagnosticsParams = PublishDiagnosticsParams
    
    61
    +
    
    62
    +data LanguageContextEnv config =
    
    63
    +  LanguageContextEnv
    
    64
    +    { resSendMessage :: FromServerMessage -> IO () }
    
    65
    +
    
    66
    +
    
    67
    +sendNotification ::
    
    68
    +  forall (m :: Method ServerToClient Notification) f config.
    
    69
    +  MonadLsp config f =>
    
    70
    +  SServerMethod m ->
    
    71
    +  MessageParams m ->
    
    72
    +  f ()
    
    73
    +sendNotification m params =
    
    74
    +  let msg = TNotificationMessage { _method = m, _params = params }
    
    75
    +   in case splitServerMethod m of
    
    76
    +        IsServerNot -> sendToClient $ fromServerNot msg
    
    77
    +
    
    78
    +type Method :: MessageDirection -> MessageKind -> Type
    
    79
    +data Method f t where
    
    80
    +  Method_TextDocumentImplementation :: Method ClientToServer Request
    
    81
    +  Method_TextDocumentTypeDefinition :: Method ClientToServer Request
    
    82
    +  Method_WorkspaceWorkspaceFolders :: Method ServerToClient Request
    
    83
    +  Method_WorkspaceConfiguration :: Method ServerToClient Request
    
    84
    +  Method_TextDocumentDocumentColor :: Method ClientToServer Request
    
    85
    +  Method_TextDocumentColorPresentation :: Method ClientToServer Request
    
    86
    +  Method_TextDocumentFoldingRange :: Method ClientToServer Request
    
    87
    +  Method_TextDocumentDeclaration :: Method ClientToServer Request
    
    88
    +  Method_TextDocumentSelectionRange :: Method ClientToServer Request
    
    89
    +  Method_WindowWorkDoneProgressCreate :: Method ServerToClient Request
    
    90
    +  Method_TextDocumentPrepareCallHierarchy :: Method ClientToServer Request
    
    91
    +  Method_CallHierarchyIncomingCalls :: Method ClientToServer Request
    
    92
    +  Method_CallHierarchyOutgoingCalls :: Method ClientToServer Request
    
    93
    +  Method_TextDocumentSemanticTokensFull :: Method ClientToServer Request
    
    94
    +  Method_TextDocumentSemanticTokensFullDelta :: Method ClientToServer Request
    
    95
    +  Method_TextDocumentSemanticTokensRange :: Method ClientToServer Request
    
    96
    +  Method_WorkspaceSemanticTokensRefresh :: Method ServerToClient Request
    
    97
    +  Method_WindowShowDocument :: Method ServerToClient Request
    
    98
    +  Method_TextDocumentLinkedEditingRange :: Method ClientToServer Request
    
    99
    +  Method_WorkspaceWillCreateFiles :: Method ClientToServer Request
    
    100
    +  Method_WorkspaceWillRenameFiles :: Method ClientToServer Request
    
    101
    +  Method_WorkspaceWillDeleteFiles :: Method ClientToServer Request
    
    102
    +  Method_TextDocumentMoniker :: Method ClientToServer Request
    
    103
    +  Method_TextDocumentPrepareTypeHierarchy :: Method ClientToServer Request
    
    104
    +  Method_TypeHierarchySupertypes :: Method ClientToServer Request
    
    105
    +  Method_TypeHierarchySubtypes :: Method ClientToServer Request
    
    106
    +  Method_TextDocumentInlineValue :: Method ClientToServer Request
    
    107
    +  Method_WorkspaceInlineValueRefresh :: Method ServerToClient Request
    
    108
    +  Method_TextDocumentInlayHint :: Method ClientToServer Request
    
    109
    +  Method_InlayHintResolve :: Method ClientToServer Request
    
    110
    +  Method_WorkspaceInlayHintRefresh :: Method ServerToClient Request
    
    111
    +  Method_TextDocumentDiagnostic :: Method ClientToServer Request
    
    112
    +  Method_WorkspaceDiagnostic :: Method ClientToServer Request
    
    113
    +  Method_WorkspaceDiagnosticRefresh :: Method ServerToClient Request
    
    114
    +  Method_ClientRegisterCapability :: Method ServerToClient Request
    
    115
    +  Method_ClientUnregisterCapability :: Method ServerToClient Request
    
    116
    +  Method_Initialize :: Method ClientToServer Request
    
    117
    +  Method_Shutdown :: Method ClientToServer Request
    
    118
    +  Method_WindowShowMessageRequest :: Method ServerToClient Request
    
    119
    +  Method_TextDocumentWillSaveWaitUntil :: Method ClientToServer Request
    
    120
    +  Method_TextDocumentCompletion :: Method ClientToServer Request
    
    121
    +  Method_CompletionItemResolve :: Method ClientToServer Request
    
    122
    +  Method_TextDocumentHover :: Method ClientToServer Request
    
    123
    +  Method_TextDocumentSignatureHelp :: Method ClientToServer Request
    
    124
    +  Method_TextDocumentDefinition :: Method ClientToServer Request
    
    125
    +  Method_TextDocumentReferences :: Method ClientToServer Request
    
    126
    +  Method_TextDocumentDocumentHighlight :: Method ClientToServer Request
    
    127
    +  Method_TextDocumentDocumentSymbol :: Method ClientToServer Request
    
    128
    +  Method_TextDocumentCodeAction :: Method ClientToServer Request
    
    129
    +  Method_CodeActionResolve :: Method ClientToServer Request
    
    130
    +  Method_WorkspaceSymbol :: Method ClientToServer Request
    
    131
    +  Method_WorkspaceSymbolResolve :: Method ClientToServer Request
    
    132
    +  Method_TextDocumentCodeLens :: Method ClientToServer Request
    
    133
    +  Method_CodeLensResolve :: Method ClientToServer Request
    
    134
    +  Method_WorkspaceCodeLensRefresh :: Method ServerToClient Request
    
    135
    +  Method_TextDocumentDocumentLink :: Method ClientToServer Request
    
    136
    +  Method_DocumentLinkResolve :: Method ClientToServer Request
    
    137
    +  Method_TextDocumentFormatting :: Method ClientToServer Request
    
    138
    +  Method_TextDocumentRangeFormatting :: Method ClientToServer Request
    
    139
    +  Method_TextDocumentOnTypeFormatting :: Method ClientToServer Request
    
    140
    +  Method_TextDocumentRename :: Method ClientToServer Request
    
    141
    +  Method_TextDocumentPrepareRename :: Method ClientToServer Request
    
    142
    +  Method_WorkspaceExecuteCommand :: Method ClientToServer Request
    
    143
    +  Method_WorkspaceApplyEdit :: Method ServerToClient Request
    
    144
    +  Method_WorkspaceDidChangeWorkspaceFolders :: Method ClientToServer Notification
    
    145
    +  Method_WindowWorkDoneProgressCancel :: Method ClientToServer Notification
    
    146
    +  Method_WorkspaceDidCreateFiles :: Method ClientToServer Notification
    
    147
    +  Method_WorkspaceDidRenameFiles :: Method ClientToServer Notification
    
    148
    +  Method_WorkspaceDidDeleteFiles :: Method ClientToServer Notification
    
    149
    +  Method_NotebookDocumentDidOpen :: Method ClientToServer Notification
    
    150
    +  Method_NotebookDocumentDidChange :: Method ClientToServer Notification
    
    151
    +  Method_NotebookDocumentDidSave :: Method ClientToServer Notification
    
    152
    +  Method_NotebookDocumentDidClose :: Method ClientToServer Notification
    
    153
    +  Method_Initialized :: Method ClientToServer Notification
    
    154
    +  Method_Exit :: Method ClientToServer Notification
    
    155
    +  Method_WorkspaceDidChangeConfiguration :: Method ClientToServer Notification
    
    156
    +  Method_WindowShowMessage :: Method ServerToClient Notification
    
    157
    +  Method_WindowLogMessage :: Method ServerToClient Notification
    
    158
    +  Method_TelemetryEvent :: Method ServerToClient Notification
    
    159
    +  Method_TextDocumentDidOpen :: Method ClientToServer Notification
    
    160
    +  Method_TextDocumentDidChange :: Method ClientToServer Notification
    
    161
    +  Method_TextDocumentDidClose :: Method ClientToServer Notification
    
    162
    +  Method_TextDocumentDidSave :: Method ClientToServer Notification
    
    163
    +  Method_TextDocumentWillSave :: Method ClientToServer Notification
    
    164
    +  Method_WorkspaceDidChangeWatchedFiles :: Method ClientToServer Notification
    
    165
    +  Method_TextDocumentPublishDiagnostics :: Method ServerToClient Notification
    
    166
    +  Method_SetTrace :: Method ClientToServer Notification
    
    167
    +  Method_LogTrace :: Method ServerToClient Notification
    
    168
    +  Method_CancelRequest :: Method f Notification
    
    169
    +  Method_Progress :: Method f Notification
    
    170
    +  Method_CustomMethod :: Symbol -> Method f t
    
    171
    +
    
    172
    +type SMethod :: forall f t . Method f t -> Type
    
    173
    +data SMethod m where
    
    174
    +  SMethod_TextDocumentImplementation :: SMethod Method_TextDocumentImplementation
    
    175
    +  SMethod_TextDocumentTypeDefinition :: SMethod Method_TextDocumentTypeDefinition
    
    176
    +  SMethod_WorkspaceWorkspaceFolders :: SMethod Method_WorkspaceWorkspaceFolders
    
    177
    +  SMethod_WorkspaceConfiguration :: SMethod Method_WorkspaceConfiguration
    
    178
    +  SMethod_TextDocumentDocumentColor :: SMethod Method_TextDocumentDocumentColor
    
    179
    +  SMethod_TextDocumentColorPresentation :: SMethod Method_TextDocumentColorPresentation
    
    180
    +  SMethod_TextDocumentFoldingRange :: SMethod Method_TextDocumentFoldingRange
    
    181
    +  SMethod_TextDocumentDeclaration :: SMethod Method_TextDocumentDeclaration
    
    182
    +  SMethod_TextDocumentSelectionRange :: SMethod Method_TextDocumentSelectionRange
    
    183
    +  SMethod_WindowWorkDoneProgressCreate :: SMethod Method_WindowWorkDoneProgressCreate
    
    184
    +  SMethod_TextDocumentPrepareCallHierarchy :: SMethod Method_TextDocumentPrepareCallHierarchy
    
    185
    +  SMethod_CallHierarchyIncomingCalls :: SMethod Method_CallHierarchyIncomingCalls
    
    186
    +  SMethod_CallHierarchyOutgoingCalls :: SMethod Method_CallHierarchyOutgoingCalls
    
    187
    +  SMethod_TextDocumentSemanticTokensFull :: SMethod Method_TextDocumentSemanticTokensFull
    
    188
    +  SMethod_TextDocumentSemanticTokensFullDelta :: SMethod Method_TextDocumentSemanticTokensFullDelta
    
    189
    +  SMethod_TextDocumentSemanticTokensRange :: SMethod Method_TextDocumentSemanticTokensRange
    
    190
    +  SMethod_WorkspaceSemanticTokensRefresh :: SMethod Method_WorkspaceSemanticTokensRefresh
    
    191
    +  SMethod_WindowShowDocument :: SMethod Method_WindowShowDocument
    
    192
    +  SMethod_TextDocumentLinkedEditingRange :: SMethod Method_TextDocumentLinkedEditingRange
    
    193
    +  SMethod_WorkspaceWillCreateFiles :: SMethod Method_WorkspaceWillCreateFiles
    
    194
    +  SMethod_WorkspaceWillRenameFiles :: SMethod Method_WorkspaceWillRenameFiles
    
    195
    +  SMethod_WorkspaceWillDeleteFiles :: SMethod Method_WorkspaceWillDeleteFiles
    
    196
    +  SMethod_TextDocumentMoniker :: SMethod Method_TextDocumentMoniker
    
    197
    +  SMethod_TextDocumentPrepareTypeHierarchy :: SMethod Method_TextDocumentPrepareTypeHierarchy
    
    198
    +  SMethod_TypeHierarchySupertypes :: SMethod Method_TypeHierarchySupertypes
    
    199
    +  SMethod_TypeHierarchySubtypes :: SMethod Method_TypeHierarchySubtypes
    
    200
    +  SMethod_TextDocumentInlineValue :: SMethod Method_TextDocumentInlineValue
    
    201
    +  SMethod_WorkspaceInlineValueRefresh :: SMethod Method_WorkspaceInlineValueRefresh
    
    202
    +  SMethod_TextDocumentInlayHint :: SMethod Method_TextDocumentInlayHint
    
    203
    +  SMethod_InlayHintResolve :: SMethod Method_InlayHintResolve
    
    204
    +  SMethod_WorkspaceInlayHintRefresh :: SMethod Method_WorkspaceInlayHintRefresh
    
    205
    +  SMethod_TextDocumentDiagnostic :: SMethod Method_TextDocumentDiagnostic
    
    206
    +  SMethod_WorkspaceDiagnostic :: SMethod Method_WorkspaceDiagnostic
    
    207
    +  SMethod_WorkspaceDiagnosticRefresh :: SMethod Method_WorkspaceDiagnosticRefresh
    
    208
    +  SMethod_ClientRegisterCapability :: SMethod Method_ClientRegisterCapability
    
    209
    +  SMethod_ClientUnregisterCapability :: SMethod Method_ClientUnregisterCapability
    
    210
    +  SMethod_Initialize :: SMethod Method_Initialize
    
    211
    +  SMethod_Shutdown :: SMethod Method_Shutdown
    
    212
    +  SMethod_WindowShowMessageRequest :: SMethod Method_WindowShowMessageRequest
    
    213
    +  SMethod_TextDocumentWillSaveWaitUntil :: SMethod Method_TextDocumentWillSaveWaitUntil
    
    214
    +  SMethod_TextDocumentCompletion :: SMethod Method_TextDocumentCompletion
    
    215
    +  SMethod_CompletionItemResolve :: SMethod Method_CompletionItemResolve
    
    216
    +  SMethod_TextDocumentHover :: SMethod Method_TextDocumentHover
    
    217
    +  SMethod_TextDocumentSignatureHelp :: SMethod Method_TextDocumentSignatureHelp
    
    218
    +  SMethod_TextDocumentDefinition :: SMethod Method_TextDocumentDefinition
    
    219
    +  SMethod_TextDocumentReferences :: SMethod Method_TextDocumentReferences
    
    220
    +  SMethod_TextDocumentDocumentHighlight :: SMethod Method_TextDocumentDocumentHighlight
    
    221
    +  SMethod_TextDocumentDocumentSymbol :: SMethod Method_TextDocumentDocumentSymbol
    
    222
    +  SMethod_TextDocumentCodeAction :: SMethod Method_TextDocumentCodeAction
    
    223
    +  SMethod_CodeActionResolve :: SMethod Method_CodeActionResolve
    
    224
    +  SMethod_WorkspaceSymbol :: SMethod Method_WorkspaceSymbol
    
    225
    +  SMethod_WorkspaceSymbolResolve :: SMethod Method_WorkspaceSymbolResolve
    
    226
    +  SMethod_TextDocumentCodeLens :: SMethod Method_TextDocumentCodeLens
    
    227
    +  SMethod_CodeLensResolve :: SMethod Method_CodeLensResolve
    
    228
    +  SMethod_WorkspaceCodeLensRefresh :: SMethod Method_WorkspaceCodeLensRefresh
    
    229
    +  SMethod_TextDocumentDocumentLink :: SMethod Method_TextDocumentDocumentLink
    
    230
    +  SMethod_DocumentLinkResolve :: SMethod Method_DocumentLinkResolve
    
    231
    +  SMethod_TextDocumentFormatting :: SMethod Method_TextDocumentFormatting
    
    232
    +  SMethod_TextDocumentRangeFormatting :: SMethod Method_TextDocumentRangeFormatting
    
    233
    +  SMethod_TextDocumentOnTypeFormatting :: SMethod Method_TextDocumentOnTypeFormatting
    
    234
    +  SMethod_TextDocumentRename :: SMethod Method_TextDocumentRename
    
    235
    +  SMethod_TextDocumentPrepareRename :: SMethod Method_TextDocumentPrepareRename
    
    236
    +  SMethod_WorkspaceExecuteCommand :: SMethod Method_WorkspaceExecuteCommand
    
    237
    +  SMethod_WorkspaceApplyEdit :: SMethod Method_WorkspaceApplyEdit
    
    238
    +  SMethod_WorkspaceDidChangeWorkspaceFolders :: SMethod Method_WorkspaceDidChangeWorkspaceFolders
    
    239
    +  SMethod_WindowWorkDoneProgressCancel :: SMethod Method_WindowWorkDoneProgressCancel
    
    240
    +  SMethod_WorkspaceDidCreateFiles :: SMethod Method_WorkspaceDidCreateFiles
    
    241
    +  SMethod_WorkspaceDidRenameFiles :: SMethod Method_WorkspaceDidRenameFiles
    
    242
    +  SMethod_WorkspaceDidDeleteFiles :: SMethod Method_WorkspaceDidDeleteFiles
    
    243
    +  SMethod_NotebookDocumentDidOpen :: SMethod Method_NotebookDocumentDidOpen
    
    244
    +  SMethod_NotebookDocumentDidChange :: SMethod Method_NotebookDocumentDidChange
    
    245
    +  SMethod_NotebookDocumentDidSave :: SMethod Method_NotebookDocumentDidSave
    
    246
    +  SMethod_NotebookDocumentDidClose :: SMethod Method_NotebookDocumentDidClose
    
    247
    +  SMethod_Initialized :: SMethod Method_Initialized
    
    248
    +  SMethod_Exit :: SMethod Method_Exit
    
    249
    +  SMethod_WorkspaceDidChangeConfiguration :: SMethod Method_WorkspaceDidChangeConfiguration
    
    250
    +  SMethod_WindowShowMessage :: SMethod Method_WindowShowMessage
    
    251
    +  SMethod_WindowLogMessage :: SMethod Method_WindowLogMessage
    
    252
    +  SMethod_TelemetryEvent :: SMethod Method_TelemetryEvent
    
    253
    +  SMethod_TextDocumentDidOpen :: SMethod Method_TextDocumentDidOpen
    
    254
    +  SMethod_TextDocumentDidChange :: SMethod Method_TextDocumentDidChange
    
    255
    +  SMethod_TextDocumentDidClose :: SMethod Method_TextDocumentDidClose
    
    256
    +  SMethod_TextDocumentDidSave :: SMethod Method_TextDocumentDidSave
    
    257
    +  SMethod_TextDocumentWillSave :: SMethod Method_TextDocumentWillSave
    
    258
    +  SMethod_WorkspaceDidChangeWatchedFiles :: SMethod Method_WorkspaceDidChangeWatchedFiles
    
    259
    +  SMethod_TextDocumentPublishDiagnostics :: SMethod Method_TextDocumentPublishDiagnostics
    
    260
    +  SMethod_SetTrace :: SMethod Method_SetTrace
    
    261
    +  SMethod_LogTrace :: SMethod Method_LogTrace
    
    262
    +  SMethod_CancelRequest :: SMethod Method_CancelRequest
    
    263
    +  SMethod_Progress :: SMethod Method_Progress
    
    264
    +
    
    265
    +type SServerMethod (m :: Method ServerToClient t) = SMethod m
    
    266
    +
    
    267
    +data MessageDirection = ServerToClient | ClientToServer
    
    268
    +
    
    269
    +data MessageKind = Notification | Request
    
    270
    +
    
    271
    +
    
    272
    +type ServerNotOrReq :: forall t. Method ServerToClient t -> Type
    
    273
    +data ServerNotOrReq m where
    
    274
    +  IsServerNot ::
    
    275
    +    ( TMessage m ~ TNotificationMessage m
    
    276
    +    ) =>
    
    277
    +    ServerNotOrReq (m :: Method ServerToClient Notification)
    
    278
    +  IsServerReq ::
    
    279
    +    forall (m :: Method ServerToClient Request).
    
    280
    +    ( TMessage m ~ TRequestMessage m
    
    281
    +    ) =>
    
    282
    +    ServerNotOrReq m
    
    283
    +
    
    284
    +type TMessage :: forall f t. Method f t -> Type
    
    285
    +type family TMessage m where
    
    286
    +  TMessage (Method_CustomMethod s :: Method f t) = ()
    
    287
    +  TMessage (m :: Method f Request) = TRequestMessage m
    
    288
    +  TMessage (m :: Method f Notification) = TNotificationMessage m
    
    289
    +
    
    290
    +
    
    291
    +data TNotificationMessage (m :: Method f Notification) = TNotificationMessage
    
    292
    +  { _method :: SMethod m
    
    293
    +  , _params :: MessageParams m
    
    294
    +  }
    
    295
    +
    
    296
    +data TRequestMessage (m :: Method f Request) = TRequestMessage
    
    297
    +
    
    298
    +type MessageParams :: forall f t . Method f t -> Type
    
    299
    +type family MessageParams (m ::  Method f t) where
    
    300
    +  MessageParams Method_TextDocumentPublishDiagnostics = PublishDiagnosticsParams
    
    301
    +
    
    302
    +class MonadIO m => MonadLsp config m | m -> config where
    
    303
    +  getLspEnv :: m (LanguageContextEnv config)
    
    304
    +
    
    305
    +instance MonadLsp config (LspT config) where
    
    306
    +  {-# INLINE getLspEnv #-}
    
    307
    +  getLspEnv = LspT pure
    
    308
    +
    
    309
    +
    
    310
    +{-# INLINE splitServerMethod #-}
    
    311
    +splitServerMethod :: SServerMethod m -> ServerNotOrReq m
    
    312
    +splitServerMethod = \case
    
    313
    +  SMethod_TextDocumentPublishDiagnostics -> IsServerNot
    
    314
    +  SMethod_WindowShowMessage -> IsServerNot
    
    315
    +  SMethod_WindowShowMessageRequest -> IsServerReq
    
    316
    +  SMethod_WindowShowDocument -> IsServerReq
    
    317
    +  SMethod_WindowLogMessage -> IsServerNot
    
    318
    +  SMethod_WindowWorkDoneProgressCreate -> IsServerReq
    
    319
    +  SMethod_Progress -> IsServerNot
    
    320
    +  SMethod_TelemetryEvent -> IsServerNot
    
    321
    +  SMethod_ClientRegisterCapability -> IsServerReq
    
    322
    +  SMethod_ClientUnregisterCapability -> IsServerReq
    
    323
    +  SMethod_WorkspaceWorkspaceFolders -> IsServerReq
    
    324
    +  SMethod_WorkspaceConfiguration -> IsServerReq
    
    325
    +  SMethod_WorkspaceApplyEdit -> IsServerReq
    
    326
    +  SMethod_LogTrace -> IsServerNot
    
    327
    +  SMethod_CancelRequest -> IsServerNot
    
    328
    +  SMethod_WorkspaceCodeLensRefresh -> IsServerReq
    
    329
    +  SMethod_WorkspaceSemanticTokensRefresh -> IsServerReq
    
    330
    +  SMethod_WorkspaceInlineValueRefresh -> IsServerReq
    
    331
    +  SMethod_WorkspaceInlayHintRefresh -> IsServerReq
    
    332
    +  SMethod_WorkspaceDiagnosticRefresh -> IsServerReq
    
    333
    +
    
    334
    +fromServerNot ::
    
    335
    +  forall (m :: Method ServerToClient Notification).
    
    336
    +  TMessage m ~ TNotificationMessage m =>
    
    337
    +  TNotificationMessage m ->
    
    338
    +  FromServerMessage
    
    339
    +fromServerNot m@TNotificationMessage{_method = meth} = FromServerMess meth m
    
    340
    +
    
    341
    +
    
    342
    +data FromServerMessage' a where
    
    343
    +  FromServerMess :: forall t (m :: Method ServerToClient t) a. SMethod m -> TMessage m -> FromServerMessage' a
    
    344
    +  FromServerRsp :: forall (m :: Method ClientToServer Request) a. a m -> TResponseMessage m -> FromServerMessage' a
    
    345
    +
    
    346
    +type FromServerMessage = FromServerMessage' SMethod
    
    347
    +
    
    348
    +data TResponseMessage (m :: Method f Request) = TResponseMessage
    
    349
    +
    
    350
    +sendToClient :: MonadLsp config m => FromServerMessage -> m ()
    
    351
    +sendToClient msg = do
    
    352
    +  f <- resSendMessage <$> getLspEnv
    
    353
    +  liftIO $ f msg
    
    354
    +{-# INLINE sendToClient #-}

  • testsuite/tests/profiling/should_compile/all.T
    ... ... @@ -21,3 +21,4 @@ test('T15108', [test_opts], compile, ['-O -prof -fprof-auto'])
    21 21
     test('T19894', [test_opts, extra_files(['T19894'])], multimod_compile, ['Main', '-v0 -O2 -prof -fprof-auto -iT19894'])
    
    22 22
     test('T20938', [test_opts], compile, ['-O -prof'])
    
    23 23
     test('T26056', [test_opts], compile, ['-O -prof'])
    
    24
    +test('T27121', [test_opts], compile, ['-O -prof -fprof-auto'])

  • testsuite/tests/simplCore/should_compile/T26941.hs
    1
    +{-# LANGUAGE DataKinds #-}
    
    2
    +{-# LANGUAGE GADTs #-}
    
    3
    +{-# LANGUAGE TypeOperators #-}
    
    4
    +
    
    5
    +module T26941 where
    
    6
    +
    
    7
    +import GHC.TypeLits
    
    8
    +
    
    9
    +import T26941_aux ( SMayNat(SKnown), ListH, shxHead )
    
    10
    +
    
    11
    +shsHead :: ListH (Just n : sh) Int -> SNat n
    
    12
    +shsHead shx =
    
    13
    +  case shxHead shx of
    
    14
    +    SKnown SNat -> SNat

  • testsuite/tests/simplCore/should_compile/T26941_aux.hs
    1
    +{-# LANGUAGE DataKinds #-}
    
    2
    +{-# LANGUAGE GADTs #-}
    
    3
    +{-# LANGUAGE StandaloneKindSignatures #-}
    
    4
    +{-# LANGUAGE TypeOperators #-}
    
    5
    +
    
    6
    +module T26941_aux where
    
    7
    +
    
    8
    +import Data.Kind
    
    9
    +import GHC.TypeLits
    
    10
    +
    
    11
    +shxHead :: ListH (n : sh) i -> SMayNat i n
    
    12
    +shxHead list = {-# SCC "bad_scc" #-}
    
    13
    +  ( case list of (i `ConsKnown` _) -> SKnown i )
    
    14
    +
    
    15
    +type ListH :: [Maybe Nat] -> Type -> Type
    
    16
    +data ListH sh i where
    
    17
    +  ConsKnown :: SNat n -> ListH sh i -> ListH (Just n : sh) i
    
    18
    +
    
    19
    +data SMayNat i n where
    
    20
    +  SKnown :: SNat n -> SMayNat i (Just n)

  • testsuite/tests/simplCore/should_compile/all.T
    ... ... @@ -576,6 +576,8 @@ test('T26117', [grep_errmsg(r'==')], compile, ['-O -ddump-simpl -dsuppress-uniqu
    576 576
     test('T26349',  normal, compile, ['-O -ddump-rules'])
    
    577 577
     test('T26681',  normal, compile, ['-O'])
    
    578 578
     
    
    579
    +test('T26941', [extra_files(['T26941_aux.hs']), req_profiling], multimod_compile, ['T26941', '-v0 -O -prof'])
    
    580
    +
    
    579 581
     # T26709: we expect three `case` expressions not four
    
    580 582
     test('T26709', [grep_errmsg(r'case')],
    
    581 583
            multimod_compile,