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

Commits:

5 changed files:

Changes:

  • compiler/GHC/Core/Utils.hs
    ... ... @@ -303,59 +303,72 @@ 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 while respecting Tick invariants,
    
    307
    +-- and performing small on-the-fly optimisations.
    
    308
    +--
    
    309
    +-- Prefer using 'mkTick' over explicit use of the 'Tick' constructor.
    
    310
    +--
    
    311
    +-- Small optimisations performed:
    
    312
    +--
    
    313
    +--   * Minimise the AST covered by the tick, by pushing the tick deeper into
    
    314
    +--     the expression if this doesn't change the semantics of the tick.
    
    315
    +--     For example, push runtime relevant ticks through type applications
    
    316
    +--     and type lambdas.
    
    317
    +--   * Eliminate unnecessary ticks by either absorbing them into existing ones
    
    318
    +--     or dropping them if that is valid (e.g. dropping profiling ticks around
    
    319
    +--     types, coercions and literals).
    
    320
    +--   * Split profiling ticks into counting/scoping parts so that the two parts
    
    321
    +--     can be placed independently into the AST.
    
    308 322
     mkTick :: CoreTickish -> CoreExpr -> CoreExpr
    
    309
    -mkTick t orig_expr = mkTick' id orig_expr
    
    323
    +mkTick t orig_expr = mkTick' orig_expr
    
    310 324
      where
    
    311 325
       -- Some ticks (cost-centres) can be split in two, with the
    
    312 326
       -- non-counting part having laxer placement properties.
    
    313
    -  canSplit = tickishCanSplit t && tickishPlace (mkNoCount t) /= tickishPlace t
    
    327
    +  -- See Note [Scoping ticks and counting ticks] in GHC.Types.Tickish.
    
    328
    +  can_split = tickishCanSplit t
    
    314 329
     
    
    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)]
    
    330
    +  stop_here e = Tick t e   -- Just wrap `t` around the current expression
    
    331
    +                           -- That's the default option!
    
    329 332
     
    
    330
    -    -- Cost centre ticks should never be reordered relative to each
    
    331
    -    -- other. Therefore we can stop whenever two collide.
    
    333
    +  -- mkTick' handles floating of tick `t` *into* the expression.
    
    334
    +  mkTick' :: CoreExpr -> CoreExpr
    
    335
    +  mkTick' expr = case expr of
    
    332 336
         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
    
    337
    +      | ProfNote { profNoteCC = cc1, profNoteCount = cnt1, profNoteScope = scope1 } <- t
    
    338
    +      , ProfNote { profNoteCC = cc2, profNoteCount = cnt2, profNoteScope = scope2 } <- t2
    
    339
    +      ->
    
    340
    +        -- Common up ticks with a shared cost centre.
    
    341
    +        -- Alas, if both ticks count, we are forced to retain both.
    
    342
    +        if cc1 == cc2 && (not cnt1 || not cnt2)
    
    343
    +        then
    
    344
    +          let t' = ProfNote { profNoteCC    = cc1
    
    345
    +                            , profNoteCount = cnt1 || cnt2
    
    346
    +                            , profNoteScope = scope1 || scope2
    
    347
    +                            }
    
    348
    +          in mkTick t' e
    
    349
    +        else
    
    350
    +          -- Cost centre ticks for different cost centres should never be reordered
    
    351
    +          -- relative to each other. Therefore we can stop whenever two collide.
    
    352
    +          stop_here expr
    
    353
    +
    
    354
    +      | tickishPlace t2 /= tickishPlace t
    
    355
    +      -> -- Otherwise, we assume that ticks of different
    
    356
    +         -- placements float through each other.
    
    357
    +         Tick t2 $ mkTick' e
    
    358
    +
    
    359
    +      -- For source note ticks, this is where we make sure to
    
    360
    +      -- not introduce redundant ticks.
    
    361
    +      | tickishContains t t2 -> mkTick' e  -- Drop t2
    
    362
    +      | tickishContains t2 t -> expr       -- Drop t
    
    338 363
     
    
    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)
    
    364
    +      | otherwise
    
    365
    +      -> stop_here expr   -- Always safe
    
    353 366
     
    
    354 367
         Lam x e
    
    355 368
           -- Always float through type lambdas. Even for non-type lambdas,
    
    356 369
           -- floating is allowed for all but the most strict placement rule.
    
    357 370
           | not (isRuntimeVar x) || tickishPlace t /= PlaceRuntime
    
    358
    -      -> Lam x $ mkTick' rest e
    
    371
    +      -> Lam x $ mkTick' e
    
    359 372
     
    
    360 373
           -- If it is both counting and scoped, we split the tick into its
    
    361 374
           -- two components, often allowing us to keep the counting tick on
    
    ... ... @@ -363,26 +376,41 @@ mkTick t orig_expr = mkTick' id orig_expr
    363 376
           -- The point of this is that the counting tick can probably be
    
    364 377
           -- floated, and the lambda may then be in a position to be
    
    365 378
           -- beta-reduced.
    
    366
    -      | canSplit
    
    367
    -      -> Tick (mkNoScope t) $ rest $ Lam x $ mkTick (mkNoCount t) e
    
    379
    +      | can_split
    
    380
    +      -> Tick (mkNoScope t) $ Lam x $ mkTick (mkNoCount t) e
    
    368 381
     
    
    369 382
         App f arg
    
    370 383
           -- Always float through type applications.
    
    371 384
           | not (isRuntimeArg arg)
    
    372
    -      -> App (mkTick' rest f) arg
    
    385
    +      -> App (mkTick' f) arg
    
    373 386
     
    
    374 387
           -- We can also float through constructor applications, placement
    
    375
    -      -- permitting. Again we can split.
    
    376
    -      | isSaturatedConApp expr && (tickishPlace t==PlaceCostCentre || canSplit)
    
    388
    +      -- permitting. Again we can try splitting.
    
    389
    +      | isSaturatedConApp expr
    
    390
    +      , tickishPlace t == PlaceCostCentre || can_split
    
    377 391
           -> if tickishPlace t == PlaceCostCentre
    
    378
    -         then rest $ tickHNFArgs t expr
    
    379
    -         else Tick (mkNoScope t) $ rest $ tickHNFArgs (mkNoCount t) expr
    
    392
    +         then tickHNFArgs t expr
    
    393
    +         else Tick (mkNoScope t) $ tickHNFArgs (mkNoCount t) expr
    
    394
    +
    
    395
    +    -- Ticks don't care about types, so we just float all ticks
    
    396
    +    -- through them. Note that it's not enough to check for these
    
    397
    +    -- cases at the top-level. While mkTick will never produce Core with type
    
    398
    +    -- expressions below ticks, such constructs can be the result of
    
    399
    +    -- unfoldings. We therefore make an effort to put everything into
    
    400
    +    -- the right place no matter what we start with.
    
    401
    +    Cast e co   -> mkCast (mkTick' e) co
    
    402
    +
    
    403
    +    -- Float ticks into 'unsafeCoerce' the same way we would do with a cast.
    
    404
    +    Case scrut bndr ty alts@[Alt ac abs _rhs]
    
    405
    +      | Just rhs <- isUnsafeEqualityCase scrut bndr alts
    
    406
    +      -> Case scrut bndr ty [Alt ac abs (mkTick' rhs)]
    
    380 407
     
    
    381 408
         Var x
    
    382
    -      | notFunction && tickishPlace t == PlaceCostCentre
    
    383
    -      -> rest expr  -- Drop t
    
    384
    -      | notFunction && canSplit
    
    385
    -      -> Tick (mkNoScope t) $ rest expr
    
    409
    +      | notFunction
    
    410
    +      , tickishPlace t == PlaceCostCentre || can_split
    
    411
    +      -> if tickishPlace t == PlaceCostCentre
    
    412
    +         then expr -- Drop tick t entirely
    
    413
    +         else Tick (mkNoScope t) expr
    
    386 414
           where
    
    387 415
             -- SCCs can be eliminated on variables provided the variable
    
    388 416
             -- is not a function.  In these cases the SCC makes no difference:
    
    ... ... @@ -392,12 +420,26 @@ mkTick t orig_expr = mkTick' id orig_expr
    392 420
             -- when the function is called, so we must retain those.
    
    393 421
             notFunction = not (isFunTy (idType x))
    
    394 422
     
    
    395
    -    Lit{}
    
    396
    -      | tickishPlace t == PlaceCostCentre
    
    397
    -      -> rest expr   -- Drop t
    
    398
    -
    
    399
    -    -- Catch-all: Annotate where we stand
    
    400
    -    _any -> Tick t $ rest expr
    
    423
    +    -- It doesn't make sense to wrap static data (such as coercions, types and literals)
    
    424
    +    -- in a tick which compiles to code, as the code will never be run.
    
    425
    +    --
    
    426
    +    -- It is in fact actively harmful, because Core Lint will fail on a
    
    427
    +    -- coercion binding such as let co = <scc> (...), see #26941.
    
    428
    +    -- It makes more sense to discard the cost centre tick rather than weakening
    
    429
    +    -- Core Lint.
    
    430
    +    e@(Coercion {})
    
    431
    +      | tickishIsCode t
    
    432
    +      -> e
    
    433
    +    e@(Type {})
    
    434
    +      | tickishIsCode t
    
    435
    +      -> e
    
    436
    +    e@(Lit {})
    
    437
    +      | tickishIsCode t
    
    438
    +      -> e
    
    439
    +
    
    440
    +    -- Catch-all: annotate where we stand.
    
    441
    +    -- In particular (but not only): Let, most Cases.
    
    442
    +    _any -> Tick t expr
    
    401 443
     
    
    402 444
     mkTicks :: [CoreTickish] -> CoreExpr -> CoreExpr
    
    403 445
     mkTicks ticks expr = foldr mkTick expr ticks
    

  • compiler/GHC/Types/Tickish.hs
    ... ... @@ -261,6 +261,10 @@ Ticks have two independent attributes:
    261 261
     
    
    262 262
          See Note [Scoped ticks]
    
    263 263
     
    
    264
    +Note that profiling notes which both count and scope can be split into two
    
    265
    +separate ticks, one that counts and doesn't scope and one that scopes and doesn't
    
    266
    +count; see 'tickishCanSplit', 'mkNoCount' and 'mkNoScope'.
    
    267
    +
    
    264 268
     Note [Counting ticks]
    
    265 269
     ~~~~~~~~~~~~~~~~~~~~
    
    266 270
     The following ticks count:
    
    ... ... @@ -451,7 +455,7 @@ data TickishPlacement =
    451 455
         -- legal placement rule for counting ticks.
    
    452 456
         -- NB: We generally try to move these as close to the relevant
    
    453 457
         -- 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)`.
    
    458
    +    -- type arguments. E.g. we create `(tick f) @Bool` instead of `tick (f @Bool)`.
    
    455 459
         PlaceRuntime
    
    456 460
     
    
    457 461
         -- | As @PlaceRuntime@, but we float the tick through all
    

  • 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,