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

Commits:

5 changed files:

Changes:

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -303,101 +303,194 @@ 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)]
    
    327
    +  stop_here e = Tick t e   -- Just wrap `t` around the current expression
    
    328
    +                           -- That's the default option!
    
    329 329
     
    
    330
    -    -- Cost centre ticks should never be reordered relative to each
    
    331
    -    -- other. Therefore we can stop whenever two collide.
    
    330
    +  -- mkTick' handles floating of tick `t` *into* the expression.
    
    331
    +  mkTick' :: CoreExpr -> CoreExpr
    
    332
    +  mkTick' expr = case expr of
    
    332 333
         Tick t2 e
    
    333
    -      | ProfNote{} <- t2, ProfNote{} <- t -> Tick t $ rest expr
    
    334 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
    
    335
    +      -- Common up ticks when possible, including profiling ticks that
    
    336
    +      -- share a cost centre and source notes that subsume one another.
    
    337
    +      | Just t' <- combineTickish_maybe t t2
    
    338
    +      -> mkTick t' e
    
    338 339
     
    
    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
    
    340
    +      -- Profiling ticks for different cost centres should never be reordered
    
    341
    +      -- relative to each other. Therefore, we stop whenever two collide.
    
    342
    +      | ProfNote {} <- t
    
    343
    +      , ProfNote {} <- t2
    
    344
    +      -> stop_here expr
    
    344 345
     
    
    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)
    
    346
    +      -- Ticks of different placements float through each other, so that each
    
    347
    +      -- tick can be floated into its expected position in the AST.
    
    348
    +      -- See Note [Tickish placement] in GHC.Types.Tickish.
    
    349
    +      | tickishPlace t2 /= tickishPlace t
    
    350
    +      -> Tick t2 $ mkTick' e
    
    351
    +
    
    352
    +      | otherwise
    
    353
    +      -> stop_here expr   -- Always safe
    
    353 354
     
    
    354 355
         Lam x e
    
    355 356
           -- Always float through type lambdas. Even for non-type lambdas,
    
    356 357
           -- floating is allowed for all but the most strict placement rule.
    
    357 358
           | not (isRuntimeVar x) || tickishPlace t /= PlaceRuntime
    
    358
    -      -> Lam x $ mkTick' rest e
    
    359
    +      -> Lam x $ mkTick' e
    
    359 360
     
    
    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
    
    361
    +      -- Push SCCs into lambdas.
    
    362
    +      -- See PSCC2 in Note [Pushing SCCs inwards].
    
    363
    +      | can_split
    
    364
    +      -> Tick (mkNoScope t) $ Lam x $ mkTick (mkNoCount t) e
    
    368 365
     
    
    369 366
         App f arg
    
    370
    -      -- Always float through type applications.
    
    367
    +      -- All ticks float inwards through non-runtime arguments, as per
    
    368
    +      -- Note [Tickish placement] in GHC.Types.Tickish.
    
    371 369
           | not (isRuntimeArg arg)
    
    372
    -      -> App (mkTick' rest f) arg
    
    370
    +      -> App (mkTick' f) arg
    
    373 371
     
    
    374
    -      -- We can also float through constructor applications, placement
    
    375
    -      -- permitting. Again we can split.
    
    376
    -      | isSaturatedConApp expr && (tickishPlace t==PlaceCostCentre || canSplit)
    
    372
    +      -- Push SCCs into saturated constructor applications.
    
    373
    +      -- See PSCC3 in Note [Pushing SCCs inwards].
    
    374
    +      | isSaturatedConApp expr
    
    375
    +      , tickishPlace t == PlaceCostCentre || can_split
    
    377 376
           -> if tickishPlace t == PlaceCostCentre
    
    378
    -         then rest $ tickHNFArgs t expr
    
    379
    -         else Tick (mkNoScope t) $ rest $ tickHNFArgs (mkNoCount t) expr
    
    377
    +         then tickHNFArgs t expr
    
    378
    +         else Tick (mkNoScope t) $ tickHNFArgs (mkNoCount t) expr
    
    379
    +
    
    380
    +    -- Ticks don't care about types, so we just float all ticks
    
    381
    +    -- through them. Note that it's not enough to check for these
    
    382
    +    -- cases at the top-level. While mkTick will never produce Core with type
    
    383
    +    -- expressions below ticks, such constructs can be the result of
    
    384
    +    -- unfoldings. We therefore make an effort to put everything into
    
    385
    +    -- the right place no matter what we start with.
    
    386
    +    Cast e co   -> mkCast (mkTick' e) co
    
    387
    +
    
    388
    +    -- Float ticks into 'unsafeCoerce' the same way we would do with a cast.
    
    389
    +    Case scrut bndr ty alts@[Alt ac abs _rhs]
    
    390
    +      | Just rhs <- isUnsafeEqualityCase scrut bndr alts
    
    391
    +      -> Case scrut bndr ty [Alt ac abs (mkTick' rhs)]
    
    380 392
     
    
    381 393
         Var x
    
    382
    -      | notFunction && tickishPlace t == PlaceCostCentre
    
    383
    -      -> rest expr  -- Drop t
    
    384
    -      | notFunction && canSplit
    
    385
    -      -> Tick (mkNoScope t) $ rest expr
    
    394
    +      -- Drop SCCs around non-function variables.
    
    395
    +      -- See PSCC1 in Note [Pushing SCCs inwards].
    
    396
    +      | notFunction
    
    397
    +        -- Does the tick `t` contain an SCC we can drop?
    
    398
    +      , tickishPlace t == PlaceCostCentre || can_split
    
    399
    +      -> if tickishPlace t == PlaceCostCentre
    
    400
    +         then expr -- Drop pure SCC ticks:  scc<foo> (x :: Int) ==> x
    
    401
    +         else
    
    402
    +            -- Drop the scoping part of the tick, but keep the counting part.
    
    403
    +            Tick (mkNoScope t) expr
    
    386 404
           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 405
             notFunction = not (isFunTy (idType x))
    
    394 406
     
    
    395
    -    Lit{}
    
    396
    -      | tickishPlace t == PlaceCostCentre
    
    397
    -      -> rest expr   -- Drop t
    
    407
    +    -- It doesn't make sense to wrap static data (such as coercions, types and literals)
    
    408
    +    -- in a tick which compiles to code, as the code will never be run.
    
    409
    +    --
    
    410
    +    -- It is in fact actively harmful, because Core Lint will fail on a
    
    411
    +    -- coercion binding such as let co = <scc> (...), see #26941.
    
    412
    +    -- It makes more sense to discard the cost centre tick rather than weakening
    
    413
    +    -- Core Lint.
    
    414
    +    e@(Coercion {}) | tickishIsCode t -> e
    
    415
    +    e@(Type {})     | tickishIsCode t -> e
    
    416
    +    e@(Lit {})      | tickishIsCode t -> e
    
    417
    +
    
    418
    +    -- Catch-all: annotate where we stand.
    
    419
    +    -- In particular (but not only): Let, most Cases.
    
    420
    +    _any -> Tick t expr
    
    421
    +
    
    422
    +{- Note [Pushing SCCs inwards]
    
    423
    +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    424
    +Amongst all ticks, SCCs have the laxest placement properties (PlaceCostCentre,
    
    425
    +as described in Note [Tickish placement] GHC.Types.Tickish):
    
    426
    +
    
    427
    +  PSCC1: SCCs around non-function variables can be eliminated.
    
    428
    +    The cost of evaluating the variable will be attributed to its definition
    
    429
    +    site, so the SCC makes no difference. Example:
    
    430
    +
    
    431
    +      scc<foo> (x :: Int)  ==>  x
    
    398 432
     
    
    399
    -    -- Catch-all: Annotate where we stand
    
    400
    -    _any -> Tick t $ rest expr
    
    433
    +    NB: this is only valid when the variable is not a function. For example, in:
    
    434
    +
    
    435
    +      scc<foo> (f :: Int -> Int)
    
    436
    +
    
    437
    +    we must retain the cost centre annotation, as it affects the cost-centre
    
    438
    +    pointer when the function is called. Discarding the SCC in this case would
    
    439
    +    defeat the profiling mechanism entirely!
    
    440
    +
    
    441
    +  PSCC2: SCCs can be pushed into lambdas.
    
    442
    +
    
    443
    +       scc<foo> (\x -> e)  ==>  \x -> scc<foo> e
    
    444
    +
    
    445
    +  PSCC3: We can push SCCs into (saturated) constructor applications.
    
    446
    +    For example, for an arity 2 data constructor 'D':
    
    447
    +
    
    448
    +       scc<foo> (D e1 e2)  ==>  D (scc<foo> e1) (scc<foo> e2)
    
    449
    +
    
    450
    +Now, two kinds of ticks contain SCCs:
    
    451
    +
    
    452
    +  - bare SCCs (i.e. ProfNote with profNoteCounts = False, profNoteScopes = True)
    
    453
    +  - profiling ticks that both count and scope
    
    454
    +
    
    455
    +The above explanation deals with bare SCCs. When handling profiling ticks that
    
    456
    +both count and scope, we can split tick into two, so that the scoping part can
    
    457
    +be pushed inwards (or even discarded). Specifically, we perform the following
    
    458
    +transformations:
    
    459
    +
    
    460
    +  PSCC1: Drop the SCC around non-function variables, keeping only the counting
    
    461
    +    part:
    
    462
    +
    
    463
    +       scctick<foo> (x :: Int)  ==>  tick<foo> x
    
    464
    +
    
    465
    +  PSCC2: Push the SCC inside lambdas:
    
    466
    +
    
    467
    +       scctick<foo> (\x. e)  ==>  tick<foo> (\x. scc<foo> e)
    
    468
    +
    
    469
    +    NB: we must keep the counting part outside the lambda, in order to preserve
    
    470
    +    tick counter tallies – it would not be sound to push the counting part inside.
    
    471
    +
    
    472
    +  PSCC3: Push the SCC inside saturated contructor applications.
    
    473
    +
    
    474
    +       scctick<foo> (D e1 e2)  ==>  tick<foo> (D (scc<foo> e1) (scc<foo> e2))
    
    475
    +
    
    476
    +The benefit of these transformation is that the counting part, tick<foo>, can
    
    477
    +likely be floated out of the way, which may expose additional optimisation
    
    478
    +opportunities. For example:
    
    479
    +
    
    480
    +  (scctick<foo> (\x. e)) arg
    
    481
    +
    
    482
    +    ==>{PSCC2}
    
    483
    +
    
    484
    +  (tick<foo> (\x. scc<foo> e)) arg
    
    485
    +
    
    486
    +    ==>{GHC.Core.Opt.FloatOut.floatExpr, because 'tick<foo>' has no scope}
    
    487
    +
    
    488
    +  tick<foo> ((\x. scc<foo> e) arg)
    
    489
    +
    
    490
    +    ==>{beta reduction}
    
    491
    +
    
    492
    +  tick<foo> (let x = arg in scc<foo> e)
    
    493
    +-}
    
    401 494
     
    
    402 495
     mkTicks :: [CoreTickish] -> CoreExpr -> CoreExpr
    
    403 496
     mkTicks ticks expr = foldr mkTick expr ticks
    

  • 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,44 @@ 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 terms we want the tick to be placed
    
    387
    +around in the AST) is governed by 'TickishPlacement'. We generally try to push
    
    388
    +ticks inwards until they end up placed around the kind of term expected by their
    
    389
    +placement rules.
    
    390
    +
    
    391
    +From most restrictive to least restrictive placement rules:
    
    392
    +
    
    393
    +  - PlaceRuntime: counting ticks.
    
    394
    +
    
    395
    +    Ticks with 'PlaceRuntime' placement want to be placed on run-time expressions.
    
    396
    +    They can be moved through pure compile-time constructs such as other ticks,
    
    397
    +    casts or type lambdas.
    
    398
    +
    
    399
    +    This is the most restrictive placement rule for ticks, as all tickishs have
    
    400
    +    in common that they want to track runtime processes.
    
    401
    +
    
    402
    +    Any tick that counts (see Note [Counting ticks]) has 'PlaceRuntime' placement.
    
    403
    +
    
    404
    +  - PlaceNonLam: source notes.
    
    405
    +
    
    406
    +    Like PlaceRuntime, but we can also float the tick through value lambdas.
    
    407
    +    This makes sense where there is little difference between annotating the
    
    408
    +    lambda and annotating the lambda's code.
    
    409
    +
    
    410
    +  - PlaceCostCentre: non-counting profiling ticks.
    
    411
    +
    
    412
    +    In addition to floating through lambdas, cost-centre style tickishs can also
    
    413
    +    be moved from constructors and non-function variables. For example:
    
    414
    +
    
    415
    +       let x = scc<...> C (scc<...> y) (scc<...> 3) in ...
    
    416
    +
    
    417
    +    Neither the constructor application, the variable or the literal are likely
    
    418
    +    to have any cost worth mentioning. And even if 'y' names a thunk, the call
    
    419
    +    would not care about the evaluation context. Therefore, removing all
    
    420
    +    annotations in the above example is safe.
    
    378 421
     -}
    
    379 422
     
    
    380 423
     -- | Returns @True@ for ticks that can be floated upwards easily even
    
    ... ... @@ -441,35 +484,19 @@ isProfTick _ = False
    441 484
     -- annotating for example using @mkTick@. If we find that we want to
    
    442 485
     -- put a tickish on an expression ruled out here, we try to float it
    
    443 486
     -- inwards until we find a suitable expression.
    
    487
    +--
    
    488
    +-- See Note [Tickish placement].
    
    444 489
     data TickishPlacement =
    
    445 490
     
    
    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)`.
    
    491
    +    -- | Place ticks exactly on run-time expressions, moving them through pure
    
    492
    +    -- compile-time constructs such as other ticks, casts or type lambdas.
    
    455 493
         PlaceRuntime
    
    456 494
     
    
    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.
    
    495
    +    -- | As @PlaceRuntime@, but also allow to float the tick through all lambdas.
    
    460 496
       | PlaceNonLam
    
    461 497
     
    
    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.
    
    498
    +    -- | As 'PlaceNonLam', but also float through constructors, non-function
    
    499
    +    -- variables and literals.
    
    473 500
       | PlaceCostCentre
    
    474 501
     
    
    475 502
       deriving (Eq,Show)
    
    ... ... @@ -477,7 +504,9 @@ data TickishPlacement =
    477 504
     instance Outputable TickishPlacement where
    
    478 505
       ppr = text . show
    
    479 506
     
    
    480
    --- | Placement behaviour we want for the ticks
    
    507
    +-- | Placement behaviour we want for the ticks.
    
    508
    +--
    
    509
    +-- See Note [Tickish placement].
    
    481 510
     tickishPlace :: GenTickish pass -> TickishPlacement
    
    482 511
     tickishPlace n@ProfNote{}
    
    483 512
       | profNoteCount n        = PlaceRuntime
    
    ... ... @@ -486,6 +515,43 @@ tickishPlace HpcTick{} = PlaceRuntime
    486 515
     tickishPlace Breakpoint{}  = PlaceRuntime
    
    487 516
     tickishPlace SourceNote{}  = PlaceNonLam
    
    488 517
     
    
    518
    +-- | Merge two ticks into one, if that is possible.
    
    519
    +--
    
    520
    +-- Examples:
    
    521
    +--
    
    522
    +--  - combine two source note ticks if one contains the other,
    
    523
    +--  - combine a non-counting profiling tick with a non-scoping profiling tick
    
    524
    +--    for the same cost centre
    
    525
    +--  - combine two equal breakpoint ticks or HPC ticks
    
    526
    +combineTickish_maybe :: Eq (GenTickish pass)
    
    527
    +                   => GenTickish pass -> GenTickish pass -> Maybe (GenTickish pass)
    
    528
    +combineTickish_maybe
    
    529
    +  (ProfNote { profNoteCC = cc1, profNoteCount = cnt1, profNoteScope = scope1 })
    
    530
    +  (ProfNote { profNoteCC = cc2, profNoteCount = cnt2, profNoteScope = scope2 })
    
    531
    +    | cc1 == cc2
    
    532
    +    , not cnt1 || not cnt2
    
    533
    +    = Just $ ProfNote { profNoteCC    = cc1
    
    534
    +                      , profNoteCount = cnt1 || cnt2
    
    535
    +                      , profNoteScope = scope1 || scope2
    
    536
    +                      }
    
    537
    +combineTickish_maybe t1@(SourceNote sp1 n1) t2@(SourceNote sp2 n2)
    
    538
    +  | n1 == n2
    
    539
    +  , sp1 `containsSpan` sp2
    
    540
    +  = Just t1
    
    541
    +  | n1 == n2
    
    542
    +  , sp2 `containsSpan` sp1
    
    543
    +  = Just t2
    
    544
    +  -- NB: it would be possible to use 'combineRealSrcSpans' instead,
    
    545
    +  -- but that has the risk of combining many source note ticks into a single
    
    546
    +  -- tick with a huge source span.
    
    547
    +combineTickish_maybe t1@(HpcTick {}) t2@(HpcTick {})
    
    548
    +  | t1 == t2
    
    549
    +  = Just t1
    
    550
    +combineTickish_maybe t1@(Breakpoint {}) t2@(Breakpoint {})
    
    551
    +  | t1 == t2
    
    552
    +  = Just t1
    
    553
    +combineTickish_maybe _ _ = Nothing
    
    554
    +
    
    489 555
     -- | Returns whether one tick "contains" the other one, therefore
    
    490 556
     -- making the second tick redundant.
    
    491 557
     tickishContains :: Eq (GenTickish pass)
    

  • 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
    ... ... @@ -568,6 +568,8 @@ test('T26117', [grep_errmsg(r'==')], compile, ['-O -ddump-simpl -dsuppress-uniqu
    568 568
     test('T26349',  normal, compile, ['-O -ddump-rules'])
    
    569 569
     test('T26681',  normal, compile, ['-O'])
    
    570 570
     
    
    571
    +test('T26941', [extra_files(['T26941_aux.hs']), req_profiling], multimod_compile, ['T26941', '-v0 -O -prof'])
    
    572
    +
    
    571 573
     # T26709: we expect three `case` expressions not four
    
    572 574
     test('T26709', [grep_errmsg(r'case')],
    
    573 575
            multimod_compile,