<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html lang="en" style='--code-editor-font: var(--default-mono-font, "GitLab Mono"), JetBrains Mono, Menlo, DejaVu Sans Mono, Liberation Mono, Consolas, Ubuntu Mono, Courier New, andale mono, lucida console, monospace;'>
<head>
<meta content="text/html; charset=US-ASCII" http-equiv="Content-Type">
<title>
GitLab
</title>

<style data-premailer="ignore" type="text/css">
a { color: #1068bf; }
</style>


<style>img {
max-width: 100%; height: auto;
}
body {
font-size: .875rem;
}
body {
-webkit-text-shadow: rgba(255,255,255,.01) 0 0 1px;
}
body {
font-family: "GitLab Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans",Ubuntu,Cantarell,"Helvetica Neue",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji"; font-size: inherit;
}
</style>
</head>
<body style='font-size: inherit; -webkit-text-shadow: rgba(255,255,255,.01) 0 0 1px; font-family: "GitLab Sans",-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Noto Sans",Ubuntu,Cantarell,"Helvetica Neue",sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol","Noto Color Emoji";'>
<div class="content">

<h3 style="margin-top: 20px; margin-bottom: 10px;">
Sebastian Graf pushed to branch wip/T20749 at <a href="https://gitlab.haskell.org/ghc/ghc">Glasgow Haskell Compiler / GHC</a>
</h3>
<h4 style="margin-top: 10px; margin-bottom: 10px;">
Commits:
</h4>
<ul>
<li>
<strong style="font-weight: 600;"><a href="https://gitlab.haskell.org/ghc/ghc/-/commit/ad39e0ed7ec69b0f0257940d9fdb2583b19008bd">ad39e0ed</a></strong>
<div>
<span> by Sebastian Graf </span> <i> at 2024-10-24T08:15:36+02:00 </i>
</div>
<pre class="commit-message" style='white-space: pre-wrap; display: block; font-size: 14px; color: #28272d; position: relative; font-family: "GitLab Mono","JetBrains Mono","Menlo","DejaVu Sans Mono","Liberation Mono","Consolas","Ubuntu Mono","Courier New","andale mono","lucida console",monospace; word-break: break-all; word-wrap: break-word; background-color: #fbfafd; border-radius: 2px; margin: 0; padding: 8px 12px; border: 1px solid #dcdcde;'>Make DataCon workers strict in strict fields (#20749)

This patch tweaks `exprIsConApp_maybe`, `exprIsHNF` and friends, and Demand
Analysis so that they exploit and maintain strictness of DataCon workers. See
`Note [Strict fields in Core]` for details.

Very little needed to change, and it puts field seq insertion done by Tag
Inference into a new perspective: That of *implementing* strict field semantics.
Before Tag Inference, DataCon workers are strict. Afterwards they are
effectively lazy and field seqs happen around use sites. History has shown
that there is no other way to guarantee taggedness and thus the STG Strict Field
Invariant.

Knock-on changes:

  * I reworked the whole narrative around "Tag inference".
    It's now called "EPT enforcement" and I recycyled the different overview
    Notes into `Note [EPT enforcement]`.

  * `exprIsHNF` previously used `exprOkForSpeculation` on unlifted arguments
    instead of recursing into `exprIsHNF`. That regressed the termination
    analysis in CPR analysis (which simply calls out to `exprIsHNF`), so I made
    it call `exprOkForSpeculation`, too.

  * There's a small regression in Demand Analysis, visible in the changed test
    output of T16859: Previously, a field seq on a variable would give that
    variable a "used exactly once" demand, now it's "used at least once",
    because `dmdTransformDataConSig` accounts for future uses of the field
    that actually all go through the case binder (and hence won't re-enter the
    potential thunk). The difference should hardly be observable.

  * The Simplifier's fast path for data constructors only applies to lazy
    data constructors now. I observed regressions involving Data.Binary.Put's
    `Pair` data type.

  * Unfortunately, T21392 does no longer reproduce after this patch, so I marked
    it as "not broken" in order to track whether we regress again in the future.

Fixes #20749, the satisfying conclusion of an annoying saga (cf. the ideas
in #21497 and #22475).

Compiler perf generally improves, sometimes drastically:

                                                     Baseline
                                 Test    Metric          value      New value Change
--------------------------------------------------------------------------------
             ManyConstructors(normal) ghc/alloc  3,629,760,116  3,711,852,800  +2.3%  BAD
  MultiLayerModulesTH_OneShot(normal) ghc/alloc  2,502,735,440  2,565,282,888  +2.5%  BAD
                       T12707(normal) ghc/alloc    804,399,798    791,807,320  -1.6% GOOD
                       T17516(normal) ghc/alloc    964,987,744  1,008,383,520  +4.5%
                       T18140(normal) ghc/alloc     75,381,152     49,860,560 -33.9% GOOD
                      T18698b(normal) ghc/alloc    232,614,457    184,262,736 -20.8% GOOD
                       T18923(normal) ghc/alloc     62,002,368     58,301,408  -6.0% GOOD
                       T20049(normal) ghc/alloc     75,719,168     70,494,368  -6.9% GOOD
                        T3294(normal) ghc/alloc  1,237,925,833  1,157,638,992  -6.5% GOOD
                        T9233(normal) ghc/alloc    686,490,105    635,166,688  -7.5% GOOD

                            geo. mean                                          -0.7%
                            minimum                                           -33.9%
                            maximum                                            +4.5%

I looked at T17516. It seems we do a few more simplifier iterations and end up
with a larger program. It seems that some things inline more, while other things
inline less. I don't see low-hanging fruit.

I also looked at MultiLayerModulesTH_OneShot. It appears we generate a strange
join point in the `getUnique` method of `Uniquable GHC.Unit.Types.Module` that
should better call-site inline, but does not. Perhaps with !11492.

NoFib does not seem affected much either:

+-------------------------------++--+------------+-----------+---------------+-----------+
|                               ||  |      base/ | std. err. | T20749/ (rel) | std. err. |
+===============================++==+============+===========+===============+===========+
|           spectral/last-piece ||  |    7.263e8 |      0.0% |        +0.62% |      0.0% |
+===============================++==+============+===========+===============+===========+
|                     geom mean ||  |     +0.00% |           |               |           |
+-------------------------------++--+------------+-----------+---------------+-----------+

I had a look at last-piece. Nothing changes in stg-final, but there is a bit
of ... movement around Data.Map.insert's use of GHC.Exts.lazy that is gone in
stg-final.

Co-Authored-By: Jaro Reinders <jaro.reinders@gmail.com>

Metric Decrease:
    T12707
    T18140
    T18698b
    T18923
    T19695
    T20049
    T3294
    T9233
    T21839c
Metric Increase:
    ManyConstructors
    MultiLayerModulesTH_OneShot
</pre>
</li>
</ul>
<h4 style="margin-top: 10px; margin-bottom: 10px;">
30 changed files:
</h4>
<ul>
<li class="file-stats">
<a href="#377cfd14c1f92357465df995ec6537b074051322">
compiler/GHC/Builtin/Types.hs
</a>
</li>
<li class="file-stats">
<a href="#182d6a315e784018aa9c8b2ad736036b97bd5d48">
compiler/GHC/Core.hs
</a>
</li>
<li class="file-stats">
<a href="#6fcf64907fb5bdd93082d2d1eb94e4566e735865">
compiler/GHC/Core/DataCon.hs
</a>
</li>
<li class="file-stats">
<a href="#c3967bb9d3e8f5aae2dd111b5a335b48c21c1999">
compiler/GHC/Core/Opt/Arity.hs
</a>
</li>
<li class="file-stats">
<a href="#c1bf6b849619bc8d7ef37a97d993dbfaa9966f7b">
compiler/GHC/Core/Opt/CprAnal.hs
</a>
</li>
<li class="file-stats">
<a href="#8104fa1b71db6cfc4eb90cd769463d9eb9004619">
compiler/GHC/Core/Opt/DmdAnal.hs
</a>
</li>
<li class="file-stats">
<a href="#2f46b19cb85e3f7b4e72305644bc50015628c41d">
compiler/GHC/Core/Opt/Simplify/Env.hs
</a>
</li>
<li class="file-stats">
<a href="#ae6d91a5d028418bbf1431347d659e744e0a3128">
compiler/GHC/Core/Opt/Simplify/Iteration.hs
</a>
</li>
<li class="file-stats">
<a href="#f4421b4e35592648510c877ecf55b1af2b96dcee">
compiler/GHC/Core/Opt/WorkWrap/Utils.hs
</a>
</li>
<li class="file-stats">
<a href="#11ffe98a94d798427bc600e4fcfe899407536346">
compiler/GHC/Core/SimpleOpt.hs
</a>
</li>
<li class="file-stats">
<a href="#84c9d3ba34173297e7d7747e02caa2e004b164fc">
compiler/GHC/Core/Type.hs
</a>
</li>
<li class="file-stats">
<a href="#1a7aba0daeafab195716dd25432479804a55ab60">
compiler/GHC/Core/Utils.hs
</a>
</li>
<li class="file-stats">
<a href="#9a679a2680ef6061397f1987091ea9f96ffe095d">
compiler/GHC/Driver/Main.hs
</a>
</li>
<li class="file-stats">
<a href="#4ed0dc87b8bdd9324e8a181cff15caa104b9e58c">
compiler/GHC/Iface/Make.hs
</a>
</li>
<li class="file-stats">
<a href="#079d6b28856775716c78fdd4a4b35bb45a59002c">
compiler/GHC/Iface/Syntax.hs
</a>
</li>
<li class="file-stats">
<a href="#1d4e6a6ea40d42ab5454b18f3be47244545ddba5">
compiler/GHC/Stg/InferTags.hs

compiler/GHC/Stg/EnforceEpt.hs
</a>
</li>
<li class="file-stats">
<a href="#2ce456887eb4520ffe784b2e6156d21adc9a9795">
compiler/GHC/Stg/InferTags/Rewrite.hs

compiler/GHC/Stg/EnforceEpt/Rewrite.hs
</a>
</li>
<li class="file-stats">
<a href="#41a1819896b15349d24fb235a7833e514822176b">
compiler/GHC/Stg/InferTags/TagSig.hs

compiler/GHC/Stg/EnforceEpt/TagSig.hs
</a>
</li>
<li class="file-stats">
<a href="#17892de9ce0caa330833d7f7f90f0a0e071e36c2">
compiler/GHC/Stg/InferTags/Types.hs

compiler/GHC/Stg/EnforceEpt/Types.hs
</a>
</li>
<li class="file-stats">
<a href="#6c6b170dad20b4eedb2e77f6777d30c062f9bcb1">
compiler/GHC/Stg/Pipeline.hs
</a>
</li>
<li class="file-stats">
<a href="#ab7f5bb638d3dce352affbd617434b76735301b0">
compiler/GHC/Stg/Syntax.hs
</a>
</li>
<li class="file-stats">
<a href="#2f341f858154eb8e1900d5bd92a156b13ddd06f3">
compiler/GHC/StgToCmm/Bind.hs
</a>
</li>
<li class="file-stats">
<a href="#aec24e3b6966335ef5c0aac97b5106fc67c6e5ea">
compiler/GHC/StgToCmm/Closure.hs
</a>
</li>
<li class="file-stats">
<a href="#77c485508ade5a11428d9fce17204d33c5825722">
compiler/GHC/StgToCmm/Expr.hs
</a>
</li>
<li class="file-stats">
<a href="#97c256a2ec3c0a93d9cf5398d6496239520420a5">
compiler/GHC/StgToJS/ExprCtx.hs
</a>
</li>
<li class="file-stats">
<a href="#aebe2c3d616f6843166d2657bed048898add6bc9">
compiler/GHC/Tc/Instance/Class.hs
</a>
</li>
<li class="file-stats">
<a href="#7b7e8d821fd827b68e24dabab7f3d87a407c0f50">
compiler/GHC/Tc/TyCl/Build.hs
</a>
</li>
<li class="file-stats">
<a href="#d09e98aae6ad2eb59d08eac7894b68c0ab820cda">
compiler/GHC/Types/Demand.hs
</a>
</li>
<li class="file-stats">
<a href="#20aaf8344f379f354fe31dd0c1c4db4ddc5b17aa">
compiler/GHC/Types/Id.hs
</a>
</li>
<li class="file-stats">
<a href="#38110817cdbc9a34d2b80a14070cabc7515c808a">
compiler/GHC/Types/Id/Info.hs
</a>
</li>
</ul>
<h5 style="margin-top: 10px; margin-bottom: 10px; font-size: .875rem;">
The diff was not included because it is too large.
</h5>

</div>
<div class="footer" style="margin-top: 10px;">
<p style="font-size: small; color: #737278;">

<br>
<a href="https://gitlab.haskell.org/ghc/ghc/-/commit/ad39e0ed7ec69b0f0257940d9fdb2583b19008bd">View it on GitLab</a>.
<br>
You're receiving this email because of your account on <a target="_blank" rel="noopener noreferrer" href="https://gitlab.haskell.org">gitlab.haskell.org</a>. <a href="https://gitlab.haskell.org/-/profile/notifications" target="_blank" rel="noopener noreferrer" class="mng-notif-link">Manage all notifications</a> · <a href="https://gitlab.haskell.org/help" target="_blank" rel="noopener noreferrer" class="help-link">Help</a>
<script type="application/ld+json">{"@context":"http://schema.org","@type":"EmailMessage","action":{"@type":"ViewAction","name":"View Commit","url":"https://gitlab.haskell.org/ghc/ghc/-/commit/ad39e0ed7ec69b0f0257940d9fdb2583b19008bd"}}</script>


</p>
</div>
</body>
</html>