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