Simon Peyton Jones pushed to branch wip/T27737 at Glasgow Haskell Compiler / GHC Commits: ac870ad5 by Simon Jakobi at 2026-10-28T04:40:42-04:00 X86 NCG: use 32-bit POPCNT for sub-word popcounts A 32-bit write zero-extends the result to the full register, so we don't need to emit additional code for this. We also skip emitting zero-extension instructions for the argument when it is already visibly zero-extended. For the byte-wise popcount loop from #24813, this shrinks the popcount sequence from 5 instructions to 3. Assisted-by: Claude Fable 5.1 - - - - - 53087373 by Facundo Domínguez at 2026-10-28T04:41:32-04:00 Use a ShortByteString in Serialized instead of [Word8] This makes the in-memory representation 40x more compact for all values stored in annotations. A test is added to measure the representation size of annotations specified in the compiler input. The GHC API is modified. All functions that previously handled annotations in [Word8] form now use ShortByteString. The following definitions have modified types: * GHC.findGlobalAnns * GHC.Tc.Gen.Splice.getAnnotationsByTypeRep * GHC.Core.Opt.Monad.getAnnotations * GHC.Core.Opt.Monad.getFirstAnnotations * GHC.Types.Annotations.deserializeAnns * GHC.Types.Annotations.findAnns * GHC.Types.Annotations.findAnnsByTypeRep * GHC.Serialized.Serialized * GHC.Serialized.toSerialized * GHC.Serialized.fromSerialized * GHC.Serialized.serializeWithData * GHC.Serialized.deserializeWithData * GHCi.Message.ReifyAnnotations Fixes #28002. - - - - - 3378d5aa by Simon Peyton Jones at 2026-10-30T15:40:36+00:00 Core utilities in preparation for a Simplifier refactoring This is the first of three commits for #27737. It contains small, self-contained changes to Core utilities that the Simplifier refactoring in the next commit relies on. * `doCaseToLet` moves from GHC.Core.Opt.Simplify.Iteration to GHC.Core.Utils, with new `mkFloatCase` and `okFloatCase`. * A new, global, invariant on `GHC.Core.FloatCase`: a DEFAULT case-float never has a scrutinee for which `doCaseToLet` holds; we use a let-float instead (`mkFloatCase`). Nice-to-have rather than essential, but it stops a needless case-float blocking the floating of a whole group. See Note [The FloatCase invariant] in GHC.Core. * `exprIsConApp_maybe`: fix a perf hole in `subst_bndr`, which built a `Subst` unnecessarily; use `mkFloatCase` when looking through a single-alternative case; `mkFieldSeqFloats` does not seq a strict field whose argument is unlifted and ok-for-speculation. * `mkSingleAltCase` skips `occCheckExpand` when no binder is a TyCoVar. * New `GHC.Data.OrdList.allOL`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> - - - - - 73a2f04a by Simon Peyton Jones at 2026-10-30T15:40:37+00:00 Don't push `case` inside `let` in Gentle simplification This MR refactors the Simplifier again. It was triggered by #27737, in which a join point was lost, but that led me into a larger-scale refactoring. This is the second of three commits: the first added some Core utilities, and the third improves `simplOutExpr`. I did this in dialogue with Claude but I have audited every line of the new code, revising almost all of them. Here are the highlights. * The core of #27737 is that when `sm_case_case` is off (that is, in the first "gentle" simplification), we should not do this transformation: K[ let binds in e ] --> let binds in K[ e ] See point (2) in Note [sm_case_case: switching off case continuations] and discussion on #27737. This is achieved by using `splitContForNoCaseCase` in the `Let` case of `simplExprF1`. That in turn uses `splitContArgs` to split the continuation into: a part to push inwards, and a part to keep at the outside. The same split is used for `Case`, and for `runRW#`. The invariant (COC-INV) is that when `sm_case_case` is off, the SimplCont never contains Select, StrictBind or StrictArg. * I refactored the Simplifier's `LetFloats` to use the GHC-wide data type `GHC.Core.FloatBinds`. Much nicer! And it eliminates a nasty impedance mismatch because `exprIsConApp_maybe` returns `FloatBinds`. See Note [Using FloatBinds in SimplFloats] in GHC.Core.Opt.Simplify.Env. A consequence is that the Simplifier can return a single-alternative case as a `FloatCase`, rather than as an expression, so that the lets in its alternative are not trapped inside it. That matters when case-of-case is off: `rebuildWithFloats` can do case-of-known-constructor on the result directly, instead of `exprIsConApp_maybe` walking down through the case and all the lets every time, which was quadratic (T18223). See Note [Floating single-alternative cases] in GHC.Core.Opt.Simplify.Iteration. The FloatCase is wrapped around its body only when the floats are finally emitted, by `simplWrapFloats`, which uses `mkCase`, so we lose none of the usual case tidying (case merging, identity case, etc). See Note [Wrapping case-floats with mkCase] in GHC.Core.Opt.Simplify.Utils. * `prepareBinding`/`doFloatFromRhs` is simpler: a group of floats leaves the RHS of a let-binding only if every one is a let-binding that we are prepared to float (lazy, or ok-for-speculation, etc); case-floats and tick-floats never do. The per-group `FloatFlag` machinery is gone. See Note [doFloatFromRhs] in GHC.Core.Opt.Simplify.Env. * Casts. When case-of-case is off, `splitContArgs` pushes a cast inwards only if it is followed by an application. Pushing a cast into every alternative of a multi-way case duplicates the coercion (quadratically, for a derived Generic `from`: T5642, T16577) and defeats cast worker/wrapper. See Note [Do not push a cast inwards unnecessarily] in GHC.Core.Opt.Simplify.Utils. Smaller changes * `contIsDupable` treats a `Select` with "unpacking alternatives" (case x of K a b -> b, possibly nested) as dupable, so that CPR unboxing cancels with the boxing instead of making a join point. See Note [Duplicating unpacking continuations] in GHC.Core.Opt.Simplify.Utils. * `reallyRebuildCase` does `prepareAlts` first, then splits into `rebuildSingleAltCase` (no mkDupableCont needed) and `rebuildMultiAltCase`. `simplAlt` returns the simplified alternative in pieces (con, bndrs, floats, rhs) rather than floats that mention the alternative's binders. * `makeTrivial` returns only let-bindings (type `OrdList CoreBind`), and declines to bind an unlifted expression that is not ok-for-speculation. See Note [Cannot trivialise] in GHC.Core.Opt.Simplify.Iteration. * `abstractFloats` takes and returns `SimplFloats`; it is only ever given let-bindings (a postcondition of `prepareBinding`), so the former panic on a case-float (T27737a) cannot happen. * A `Case`'s type is forced exactly when the `Case` is built, by `returnCase`; see Note [Avoiding space leaks in OutType]. * Note [Floating a prefix of the floats] records an opportunity we tried and did not keep. Testsuite: new test T27737a; accept changed output for T20510 and show-bytecode-hpc. Metric Decrease: CoOpt_Read T18730 T26425 T26989 Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> - - - - - 17df08ba by Simon Peyton Jones at 2026-10-30T15:40:37+00:00 Improve simplOutExpr, and never push a continuation into simplified alternatives This is the third of three commits for #27737. * I improved `simplOutExpr` so that it is less ad-hoc, and occasionally reduces Simplifier iterations. See new Note [Re-simplifying an OutExpr]. This was a bit more subtle than I had expected, as you'll see from the Note, but the result is nice. * Recognise and document a potential variable capture described in Note [Rebuilding a case with simplified alternatives]. It doesn't actually happen today, but it /could/ so the Note describes how it is avoided. That in turn leads to some nice refactoring of `reallyRebuildCase`, allowing me to get rid of `simplAltBinders`, `simplAltIdBinder` and `simplAltExprF`, and some SimplAltFlag plumbing. Nice. * `mkDupableCont` now duplicates a lazy, `exprIsDupable` argument instead of let-binding it as `karg`, saving an iteration (T13056). See Note [Duplicating small arguments]. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> - - - - - 35 changed files: - + changelog.d/T28002 - + changelog.d/T28002-api - + changelog.d/ncg-x86-subword-popcnt - compiler/GHC.hs - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/Core.hs - compiler/GHC/Core/Opt/Monad.hs - compiler/GHC/Core/Opt/OccurAnal.hs - compiler/GHC/Core/Opt/Simplify/Env.hs - compiler/GHC/Core/Opt/Simplify/Iteration.hs - compiler/GHC/Core/Opt/Simplify/Utils.hs - compiler/GHC/Core/SimpleOpt.hs - compiler/GHC/Core/Utils.hs - compiler/GHC/Data/OrdList.hs - compiler/GHC/Driver/Config/Core/Opt/Simplify.hs - compiler/GHC/Tc/Gen/Splice.hs - compiler/GHC/Types/Annotations.hs - compiler/GHC/Utils/Outputable.hs - libraries/ghc-boot/GHC/Serialized.hs - libraries/ghci/GHCi/Message.hs - libraries/ghci/GHCi/TH.hs - libraries/ghci/GHCi/TH/Binary.hs - testsuite/tests/annotations/should_run/Makefile - + testsuite/tests/annotations/should_run/T16841.hs - + testsuite/tests/annotations/should_run/T16841.stdout - testsuite/tests/annotations/should_run/all.T - + testsuite/tests/codeGen/should_gen_asm/T24813.asm - + testsuite/tests/codeGen/should_gen_asm/T24813.cmm - testsuite/tests/codeGen/should_gen_asm/all.T - testsuite/tests/dmdanal/should_compile/T20510.stderr - testsuite/tests/plugins/T26761Plugin.hs - testsuite/tests/plugins/all.T - testsuite/tests/show-bytecode/show-bytecode-hpc.stdout - + testsuite/tests/simplCore/should_compile/T27737a.hs - testsuite/tests/simplCore/should_compile/all.T The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e2d74292f46f9e67ed61bc9babaa124... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/e2d74292f46f9e67ed61bc9babaa124... You're receiving this email because of your account on gitlab.haskell.org. Manage all notifications: https://gitlab.haskell.org/-/profile/notifications | Help: https://gitlab.haskell.org/help