[Git][ghc/ghc][wip/andreask/occ_anal_tuning] 15 commits: testsuite: Use ghci_ways to set ways in PackedDataCon/UnboxedTuples/UnliftedDataTypeInterp tests
by Andreas Klebinger (@AndreasK) 10 Oct '25
by Andreas Klebinger (@AndreasK) 10 Oct '25
10 Oct '25
Andreas Klebinger pushed to branch wip/andreask/occ_anal_tuning at Glasgow Haskell Compiler / GHC
Commits:
1275d360 by Matthew Pickering at 2025-10-03T06:05:56-04:00
testsuite: Use ghci_ways to set ways in PackedDataCon/UnboxedTuples/UnliftedDataTypeInterp tests
These tests reimplemented the logic from `valid_way` in order to
determine what ways to run. It's easier to use this combination of
`only_ways` and `extra_ways` to only run in GHCi ways and always run in
GHCi ways.
- - - - -
c06b534b by Matthew Pickering at 2025-10-03T06:06:40-04:00
Rename interpreterBackend to bytecodeBackend
This is preparation for creating bytecode files.
The "interpreter" is one way in which we can run bytecode objects. It is
more accurate to describe that the backend produces bytecode, rather
than the means by which the code will eventually run.
The "interpreterBackend" binding is left as a deprecated alias.
- - - - -
41bdb16f by Andreas Klebinger at 2025-10-06T18:04:34-04:00
Add a perf test for #26425
- - - - -
1da0c700 by Andreas Klebinger at 2025-10-06T18:05:14-04:00
Testsuite: Silence warnings about Wx-partial in concprog001
- - - - -
7471eb6a by sheaf at 2025-10-07T21:39:43-04:00
Improve how we detect user type errors in types
This commit cleans up all the code responsible for detecting whether a
type contains "TypeError msg" applications nested inside it. All the
logic is now in 'userTypeError_maybe', which is always deep. Whether
it looks inside type family applications is determined by the passed-in
boolean flag:
- When deciding whether a constraint is definitely insoluble, don't
look inside type family applications, as they may still reduce -- in
which case the TypeError could disappear.
- When reporting unsolved constraints, look inside type family
applications: they had the chance to reduce but didn't, and the
custom type error might contain valuable information.
All the details are explained in Note [Custom type errors in constraints]
in GHC.Tc.Types.Constraint.
Another benefit of this change is that it allows us to get rid of the
deeply dodgy 'getUserTypeErrorMsg' function.
This commit also improves the detection of custom type errors, for
example in equality constraints:
TypeError blah ~# rhs
It used to be the case that we didn't detect the TypeError on the LHS,
because we never considered that equality constraints could be insoluble
due to the presence of custom type errors. Addressing this oversight
improves detection of redundant pattern match warnings, fixing #26400.
- - - - -
29955267 by Rodrigo Mesquita at 2025-10-07T21:40:25-04:00
cleanup: Drop obsolete settings from config.mk.in
These values used to be spliced into the bindist's `config.mk` s.t. when
`make` was run, the values were read and written into the bindist installation `settings` file.
However, we now carry these values to the bindist directly in the
default.target toolchain file, and `make` writes almost nothing to
`settings` now (see #26227)
The entries deleted in this MR were already unused.
Fixes #26478
- - - - -
f7adfed2 by ARATA Mizuki at 2025-10-08T08:37:24-04:00
T22033 is only relevant if the word size is 64-bit
Fixes #25497
- - - - -
ff1650c9 by Ben Gamari at 2025-10-08T08:38:07-04:00
rts/posix: Enforce iteration limit on heap reservation logic
Previously we could loop indefinitely when attempting to get an address
space reservation for our heap. Limit the logic to 8 iterations to
ensure we instead issue a reasonable error message.
Addresses #26151.
- - - - -
01844557 by Ben Gamari at 2025-10-08T08:38:07-04:00
rts/posix: Hold on to low reservations when reserving heap
Previously when the OS gave us an address space reservation in low
memory we would immediately release it and try again. However, on some
platforms this meant that we would get the same allocation again in the
next iteration (since mmap's `hint` argument is just that, a hint).
Instead we now hold on to low reservations until we have found a
suitable heap reservation.
Fixes #26151.
- - - - -
b2c8d052 by Sven Tennie at 2025-10-08T08:38:47-04:00
Build terminfo only in upper stages in cross-builds (#26288)
Currently, there's no way to provide library paths for [n]curses for
both - build and target - in cross-builds. As stage0 is only used to
build upper stages, it should be fine to build terminfo only for them.
This re-enables building cross-compilers with terminfo.
- - - - -
c58f9a61 by Julian Ospald at 2025-10-08T08:39:36-04:00
ghc-toolchain: Drop `ld.gold` from merge object command
It's deprecated.
Also see #25716
- - - - -
2b8baada by sheaf at 2025-10-08T18:23:37-04:00
Improvements to 'mayLookIdentical'
This commit makes significant improvements to the machinery that decides
when we should pretty-print the "invisible bits" of a type, such as:
- kind applications, e.g. '@k' in 'Proxy @k ty'
- RuntimeReps, e.g. 'TYPE r'
- multiplicities and linear arrows 'a %1 -> b'
To do this, this commit refactors 'mayLookIdentical' to return **which**
of the invisible bits don't match up, e.g. in
(a %1 -> b) ~ (a %Many -> b)
we find that the invisible bit that doesn't match up is a multiplicity,
so we should set 'sdocLinearTypes = True' when pretty-printing, and with
e.g.
Proxy @k1 ~ Proxy @k2
we find that the invisible bit that doesn't match up is an invisible
TyCon argument, so we set 'sdocPrintExplicitKinds = True'.
We leverage these changes to remove the ad-hoc treatment of linearity
of data constructors with 'dataConDisplayType' and 'dataConNonLinearType'.
This is now handled by the machinery of 'pprWithInvisibleBits'.
Fixes #26335 #26340
- - - - -
129ce32d by sheaf at 2025-10-08T18:23:37-04:00
Store SDoc context in SourceError
This commits modifies the SourceError datatype which is used for
throwing and then reporting exceptions by storing all the info we need
to be able to print the SDoc, including whether we should print with
explicit kinds, explicit runtime-reps, etc.
This is done using the new datatype:
data SourceErrorContext
= SEC
!DiagOpts
!(DiagnosticOpts GhcMessage)
Now, when we come to report an error (by handling the exception), we
have access to the full context we need.
Fixes #26387
- - - - -
f9790ca8 by Ben Gamari at 2025-10-08T18:24:19-04:00
gitlab-ci: Make RELEASE_JOB an input
Rather than an undocumented variable.
- - - - -
8e2e19a7 by Andreas Klebinger at 2025-10-10T16:12:04+02:00
OccAnal: Be stricter.
* When combining usageDetails.
* When constructing core expressions.
In combineUsageDetails when combining the underlying adds we compute a
new `LocalOcc` for each entry by combining the two existing ones.
Rather than wait for those entries to be forced down the road we now
force them immediately. Speeding up T26425 by about 10% with little
effect on the common case.
We also force CoreExprs we construct in order to prevent them from
captuing the OccAnal Env massively reducing residency in some cases.
For T26425 residency went down by a factor of ~10x.
-------------------------
Metric Decrease:
T26425
-------------------------
- - - - -
115 changed files:
- .gitlab-ci.yml
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- compiler/GHC.hs
- compiler/GHC/Core/Multiplicity.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Predicate.hs
- compiler/GHC/Core/TyCo/Compare.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Data/Graph/UnVar.hs
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/Backend/Internal.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Errors.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Monad.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/CtLoc.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Utils/Unify.hs-boot
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/Types/SourceError.hs
- compiler/GHC/Types/TyThing/Ppr.hs
- compiler/GHC/Types/Unique/FM.hs
- compiler/GHC/Types/Var/Env.hs
- compiler/GHC/Utils/Error.hs
- compiler/GHC/Utils/Outputable.hs
- docs/users_guide/extending_ghc.rst
- ghc/GHCi/UI.hs
- ghc/Main.hs
- hadrian/bindist/config.mk.in
- hadrian/src/Settings/Default.hs
- rts/posix/OSMem.c
- testsuite/driver/testglobals.py
- testsuite/driver/testlib.py
- testsuite/tests/concurrent/prog001/all.T
- testsuite/tests/cpranal/should_compile/T18174.stderr
- testsuite/tests/driver/T11429c.stderr
- testsuite/tests/driver/T21682.stderr
- testsuite/tests/driver/T5313.hs
- testsuite/tests/ghc-api/T10052/T10052.hs
- testsuite/tests/ghc-api/T10942.hs
- testsuite/tests/ghc-api/T8639_api.hs
- testsuite/tests/ghc-api/annotations-literals/literals.hs
- testsuite/tests/ghc-api/apirecomp001/myghc.hs
- testsuite/tests/ghci-wasm/T26431.hs
- testsuite/tests/ghci/linking/dyn/T3372.hs
- testsuite/tests/ghci/should_run/PackedDataCon/packeddatacon.T
- testsuite/tests/ghci/should_run/UnboxedTuples/unboxedtuples.T
- testsuite/tests/ghci/should_run/UnliftedDataTypeInterp/unlifteddatatypeinterp.T
- testsuite/tests/indexed-types/should_fail/T14887.stderr
- testsuite/tests/linear/should_fail/T19361.stderr
- testsuite/tests/llvm/should_run/all.T
- + testsuite/tests/perf/compiler/T26425.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/pmcheck/should_compile/T26400.hs
- + testsuite/tests/pmcheck/should_compile/T26400.stderr
- + testsuite/tests/pmcheck/should_compile/T26400b.hs
- testsuite/tests/pmcheck/should_compile/all.T
- testsuite/tests/roles/should_compile/Roles13.stderr
- testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr
- testsuite/tests/simplCore/should_compile/T17673.stderr
- testsuite/tests/simplCore/should_compile/T18078.stderr
- testsuite/tests/simplCore/should_compile/T18995.stderr
- testsuite/tests/simplCore/should_compile/T19890.stderr
- testsuite/tests/simplCore/should_compile/T21948.stderr
- testsuite/tests/simplCore/should_compile/T21960.stderr
- testsuite/tests/simplCore/should_compile/T24808.stderr
- − testsuite/tests/simplCore/should_compile/T25713.stderr
- testsuite/tests/simplCore/should_compile/T4201.stdout
- testsuite/tests/simplCore/should_compile/T8331.stderr
- testsuite/tests/typecheck/no_skolem_info/T20232.stderr
- testsuite/tests/typecheck/should_fail/T11672.stderr
- testsuite/tests/typecheck/should_fail/T12373.stderr
- testsuite/tests/typecheck/should_fail/T15807.stderr
- testsuite/tests/typecheck/should_fail/T16074.stderr
- testsuite/tests/typecheck/should_fail/T18357a.stderr
- testsuite/tests/typecheck/should_fail/T19627.stderr
- testsuite/tests/typecheck/should_fail/T20241b.stderr
- testsuite/tests/typecheck/should_fail/T21530a.stderr
- testsuite/tests/typecheck/should_fail/UnliftedNewtypesFamilyKindFail2.stderr
- testsuite/tests/typecheck/should_fail/VisFlag1.stderr
- utils/check-exact/Parsers.hs
- utils/check-exact/Preprocess.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/MergeObjs.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3f2d549ece632573d1e36ee2c9b972…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3f2d549ece632573d1e36ee2c9b972…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/26166-move-prims] Move code-gen aux symbols from ghc-internal to rts
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
10 Oct '25
Rodrigo Mesquita pushed to branch wip/romes/26166-move-prims at Glasgow Haskell Compiler / GHC
Commits:
480471cc by Rodrigo Mesquita at 2025-10-10T14:58:21+01:00
Move code-gen aux symbols from ghc-internal to rts
These symbols were all previously defined in ghc-internal and made the
dependency structure awkward, where the rts may refer to some of these
symbols and had to work around that circular dependency the way
described in #26166.
Moreover, the code generator will produce code that uses these symbols!
Therefore, they should be available in the rts:
PRINCIPLE: If the code generator may produce code which uses this
symbol, then it should be defined in the rts rather than, say,
ghc-internal.
That said, the main motivation is towards fixing #26166.
Towards #26166. Pre-requisite of !14892
- - - - -
19 changed files:
- compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
- hadrian/src/Settings/Packages.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- rts/RtsSymbols.c
- rts/include/stg/Prim.h
- libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
- libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
- libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
- libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
- libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
- libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
- libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
- libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
- libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
- libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
- libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
- libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
- libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
- rts/rts.cabal
Changes:
=====================================
compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
=====================================
@@ -438,7 +438,7 @@ lower_MO_S_Shr lbl w0 [x, y] = case someWasmTypeFromCmmType (cmmBits w0) of
lower_MO_S_Shr _ _ _ = panic "lower_MO_S_Shr: unreachable"
-- | Lower a 'MO_MulMayOflo' operation. It's translated to a ccall to
--- @hs_mulIntMayOflo@ function in @ghc-prim/cbits/mulIntMayOflo@,
+-- @hs_mulIntMayOflo@ function in @rts/prim/mulIntMayOflo@,
-- otherwise it's quite non-trivial to implement as inline assembly.
lower_MO_MulMayOflo ::
CLabel -> Width -> [CmmExpr] -> WasmCodeGenM w (SomeWasmExpr w)
=====================================
hadrian/src/Settings/Packages.hs
=====================================
@@ -287,9 +287,6 @@ ghcInternalArgs = package ghcInternal ? do
, builder (Cabal Flags) ? flag NeedLibatomic `cabalFlag` "need-atomic"
- , builder (Cc CompileC) ? (not <$> flag CcLlvmBackend) ?
- input "**/cbits/atomic.c" ? arg "-Wno-sync-nand"
-
]
-- | RTS-specific command line arguments.
@@ -413,6 +410,9 @@ rtsPackageArgs = package rts ? do
, input "**/RetainerProfile.c" ? flag CcLlvmBackend ?
arg "-Wno-incompatible-pointer-types"
+
+ , input "**/prim/atomic.c" ? (not <$> flag CcLlvmBackend) ?
+ arg "-Wno-sync-nand"
]
mconcat
=====================================
libraries/ghc-internal/ghc-internal.cabal.in
=====================================
@@ -442,20 +442,7 @@ Library
cbits/sysconf.c
cbits/fs.c
cbits/strerror.c
- cbits/atomic.c
- cbits/bswap.c
- cbits/bitrev.c
- cbits/clz.c
- cbits/ctz.c
cbits/debug.c
- cbits/int64x2minmax.c
- cbits/longlong.c
- cbits/mulIntMayOflo.c
- cbits/pdep.c
- cbits/pext.c
- cbits/popcnt.c
- cbits/vectorQuotRem.c
- cbits/word2float.c
cbits/Stack_c.c
cmm-sources:
=====================================
rts/RtsSymbols.c
=====================================
@@ -1016,6 +1016,116 @@ extern char **environ;
#define RTS_FINI_ARRAY_SYMBOLS
#endif
+#define SymI_HasProtoAllSizes(symbol) \
+ SymI_HasProto(symbol##8) \
+ SymI_HasProto(symbol##16) \
+ SymI_HasProto(symbol##32) \
+ SymI_HasProto(symbol##64)
+
+#if !defined(arm_HOST_ARCH)
+#define RTS_ATOMICS_SYMBOLS \
+ SymI_HasProtoAllSizes(hs_atomic_add) \
+ SymI_HasProtoAllSizes(hs_atomic_sub) \
+ SymI_HasProtoAllSizes(hs_atomic_and) \
+ SymI_HasProtoAllSizes(hs_atomic_nand) \
+ SymI_HasProtoAllSizes(hs_atomic_or) \
+ SymI_HasProtoAllSizes(hs_atomic_xor) \
+ SymI_HasProtoAllSizes(hs_cmpxchg) \
+ SymI_HasProtoAllSizes(hs_xchg) \
+ SymI_HasProtoAllSizes(hs_atomicread) \
+ SymI_HasProtoAllSizes(hs_atomicwrite)
+#else
+// No atomics on arm32. See e9abcad4cc3
+#define RTS_ATOMICS_SYMBOLS
+#endif
+
+// In rts/longlong.c
+#if WORD_SIZE_IN_BITS < 64
+#define RTS_SYMBOLS_LONGLONG \
+ SymI_HasProto(hs_eq64) \
+ SymI_HasProto(hs_ne64) \
+ SymI_HasProto(hs_gtWord64) \
+ SymI_HasProto(hs_geWord64) \
+ SymI_HasProto(hs_ltWord64) \
+ SymI_HasProto(hs_leWord64) \
+ SymI_HasProto(hs_gtInt64) \
+ SymI_HasProto(hs_geInt64) \
+ SymI_HasProto(hs_ltInt64) \
+ SymI_HasProto(hs_leInt64) \
+ SymI_HasProto(hs_neg64) \
+ SymI_HasProto(hs_add64) \
+ SymI_HasProto(hs_sub64) \
+ SymI_HasProto(hs_mul64) \
+ SymI_HasProto(hs_remWord64) \
+ SymI_HasProto(hs_quotWord64) \
+ SymI_HasProto(hs_remInt64) \
+ SymI_HasProto(hs_quotInt64) \
+ SymI_HasProto(hs_and64) \
+ SymI_HasProto(hs_or64) \
+ SymI_HasProto(hs_xor64) \
+ SymI_HasProto(hs_not64) \
+ SymI_HasProto(hs_uncheckedShiftL64) \
+ SymI_HasProto(hs_uncheckedShiftRL64) \
+ SymI_HasProto(hs_uncheckedIShiftRA64) \
+ SymI_HasProto(hs_intToInt64) \
+ SymI_HasProto(hs_int64ToInt) \
+ SymI_HasProto(hs_wordToWord64) \
+ SymI_HasProto(hs_word64ToWord)
+#else
+#define RTS_SYMBOLS_LONGLONG
+#endif
+
+// rts/prim/vectorQuotRem.c and rts/prim/int64x2minmax
+#if defined(__SSE2__)
+#define RTS_SYMBOLS_VECTORQUOTREM \
+ SymI_HasProto(hs_quotInt8X16) \
+ SymI_HasProto(hs_quotInt16X8) \
+ SymI_HasProto(hs_quotInt32X4) \
+ SymI_HasProto(hs_quotInt64X2) \
+ SymI_HasProto(hs_quotWord8X16) \
+ SymI_HasProto(hs_quotWord16X8) \
+ SymI_HasProto(hs_quotWord32X4) \
+ SymI_HasProto(hs_quotWord64X2) \
+ SymI_HasProto(hs_remInt8X16) \
+ SymI_HasProto(hs_remInt16X8) \
+ SymI_HasProto(hs_remInt32X4) \
+ SymI_HasProto(hs_remInt64X2) \
+ SymI_HasProto(hs_remWord8X16) \
+ SymI_HasProto(hs_remWord16X8) \
+ SymI_HasProto(hs_remWord32X4) \
+ SymI_HasProto(hs_remWord64X2)
+#define RTS_SYMBOLS_INT64X2MINMAX \
+ SymI_HasProto(hs_minInt64X2) \
+ SymI_HasProto(hs_maxInt64X2) \
+ SymI_HasProto(hs_minWord64X2) \
+ SymI_HasProto(hs_maxWord64X2)
+#else
+#define RTS_SYMBOLS_VECTORQUOTREM
+#define RTS_SYMBOLS_INT64X2MINMAX
+#endif
+
+// Symbols on files in rts/prim/*
+#define RTS_SYMBOLS_PRIM \
+ RTS_ATOMICS_SYMBOLS \
+ RTS_SYMBOLS_INT64X2MINMAX \
+ RTS_SYMBOLS_LONGLONG \
+ RTS_SYMBOLS_VECTORQUOTREM \
+ SymI_HasProtoAllSizes(hs_bitrev) \
+ SymI_HasProto(hs_bswap16) \
+ SymI_HasProto(hs_bswap32) \
+ SymI_HasProto(hs_bswap64) \
+ SymI_HasProtoAllSizes(hs_clz) \
+ SymI_HasProtoAllSizes(hs_ctz) \
+ SymI_NeedsProto(hs_mulIntMayOflo) \
+ SymI_HasProtoAllSizes(hs_pdep) \
+ SymI_HasProtoAllSizes(hs_pext) \
+ SymI_HasProtoAllSizes(hs_pext) \
+ SymI_HasProto(hs_popcnt) \
+ SymI_HasProtoAllSizes(hs_popcnt) \
+ SymI_HasProto(hs_word2float32) \
+ SymI_HasProto(hs_word2float64)
+
+
/* entirely bogus claims about types of these symbols */
#define SymI_NeedsProto(vvv) extern void vvv(void);
#define SymI_NeedsDataProto(vvv) extern StgWord vvv[];
@@ -1038,6 +1148,7 @@ RTS_ARCH_LIBGCC_SYMBOLS
RTS_FINI_ARRAY_SYMBOLS
RTS_LIBFFI_SYMBOLS
RTS_ARM_OUTLINE_ATOMIC_SYMBOLS
+RTS_SYMBOLS_PRIM
#undef SymI_NeedsProto
#undef SymI_NeedsDataProto
@@ -1081,6 +1192,7 @@ RtsSymbolVal rtsSyms[] = {
RTS_FINI_ARRAY_SYMBOLS
RTS_LIBFFI_SYMBOLS
RTS_ARM_OUTLINE_ATOMIC_SYMBOLS
+ RTS_SYMBOLS_PRIM
SymI_HasDataProto(nonmoving_write_barrier_enabled)
{ 0, 0, STRENGTH_NORMAL, SYM_TYPE_CODE } /* sentinel */
};
=====================================
rts/include/stg/Prim.h
=====================================
@@ -2,8 +2,6 @@
*
* (c) The GHC Team, 2014-2014
*
- * Declarations for C fallback primitives implemented by 'ghc-internal' package.
- *
* Do not #include this file directly: #include "Rts.h" instead.
*
* To understand the structure of the RTS headers, see the wiki:
@@ -13,7 +11,7 @@
#pragma once
-/* libraries/ghc-internal/cbits/atomic.c */
+/* rts/prim/atomic.c */
StgWord hs_atomic_add8(StgWord x, StgWord val);
StgWord hs_atomic_add16(StgWord x, StgWord val);
StgWord hs_atomic_add32(StgWord x, StgWord val);
@@ -55,12 +53,12 @@ StgWord hs_xchg16(StgWord x, StgWord val);
StgWord hs_xchg32(StgWord x, StgWord val);
StgWord64 hs_xchg64(StgWord x, StgWord64 val);
-/* libraries/ghc-internal/cbits/bswap.c */
+/* rts/prim/bswap.c */
StgWord16 hs_bswap16(StgWord16 x);
StgWord32 hs_bswap32(StgWord32 x);
StgWord64 hs_bswap64(StgWord64 x);
-/* libraries/ghc-internal/cbits/bitrev.c
+/* rts/prim/bitrev.c
This was done as part of issue #16164.
See Note [Bit reversal primop] for more details about the implementation.*/
StgWord hs_bitrev8(StgWord x);
@@ -68,7 +66,7 @@ StgWord16 hs_bitrev16(StgWord16 x);
StgWord32 hs_bitrev32(StgWord32 x);
StgWord64 hs_bitrev64(StgWord64 x);
-/* libraries/ghc-internal/cbits/longlong.c */
+/* rts/prim/longlong.c */
#if WORD_SIZE_IN_BITS < 64
StgInt hs_eq64 (StgWord64 a, StgWord64 b);
StgInt hs_ne64 (StgWord64 a, StgWord64 b);
@@ -101,36 +99,36 @@ StgWord64 hs_wordToWord64 (StgWord w);
StgWord hs_word64ToWord (StgWord64 w);
#endif
-/* libraries/ghc-internal/cbits/pdep.c */
+/* rts/prim/pdep.c */
StgWord64 hs_pdep64(StgWord64 src, StgWord64 mask);
StgWord hs_pdep32(StgWord src, StgWord mask);
StgWord hs_pdep16(StgWord src, StgWord mask);
StgWord hs_pdep8(StgWord src, StgWord mask);
-/* libraries/ghc-internal/cbits/pext.c */
+/* rts/prim/pext.c */
StgWord64 hs_pext64(StgWord64 src, StgWord64 mask);
StgWord hs_pext32(StgWord src, StgWord mask);
StgWord hs_pext16(StgWord src, StgWord mask);
StgWord hs_pext8(StgWord src, StgWord mask);
-/* libraries/ghc-internal/cbits/popcnt.c */
+/* rts/prim/popcnt.c */
StgWord hs_popcnt8(StgWord x);
StgWord hs_popcnt16(StgWord x);
StgWord hs_popcnt32(StgWord x);
StgWord hs_popcnt64(StgWord64 x);
StgWord hs_popcnt(StgWord x);
-/* libraries/ghc-internal/cbits/word2float.c */
+/* rts/prim/word2float.c */
StgFloat hs_word2float32(StgWord x);
StgDouble hs_word2float64(StgWord x);
-/* libraries/ghc-internal/cbits/clz.c */
+/* rts/prim/clz.c */
StgWord hs_clz8(StgWord x);
StgWord hs_clz16(StgWord x);
StgWord hs_clz32(StgWord x);
StgWord hs_clz64(StgWord64 x);
-/* libraries/ghc-internal/cbits/ctz.c */
+/* rts/prim/ctz.c */
StgWord hs_ctz8(StgWord x);
StgWord hs_ctz16(StgWord x);
StgWord hs_ctz32(StgWord x);
=====================================
libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
=====================================
@@ -12,90 +12,66 @@
// FetchAddByteArrayOp_Int
-extern StgWord hs_atomic_add8(StgWord x, StgWord val);
-StgWord
-hs_atomic_add8(StgWord x, StgWord val)
+StgWord hs_atomic_add8(StgWord x, StgWord val)
{
return __sync_fetch_and_add((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_add16(StgWord x, StgWord val);
-StgWord
-hs_atomic_add16(StgWord x, StgWord val)
+StgWord hs_atomic_add16(StgWord x, StgWord val)
{
return __sync_fetch_and_add((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_add32(StgWord x, StgWord val);
-StgWord
-hs_atomic_add32(StgWord x, StgWord val)
+StgWord hs_atomic_add32(StgWord x, StgWord val)
{
return __sync_fetch_and_add((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_add64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_add64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_add64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_add((volatile StgWord64 *) x, val);
}
// FetchSubByteArrayOp_Int
-extern StgWord hs_atomic_sub8(StgWord x, StgWord val);
-StgWord
-hs_atomic_sub8(StgWord x, StgWord val)
+StgWord hs_atomic_sub8(StgWord x, StgWord val)
{
return __sync_fetch_and_sub((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_sub16(StgWord x, StgWord val);
-StgWord
-hs_atomic_sub16(StgWord x, StgWord val)
+StgWord hs_atomic_sub16(StgWord x, StgWord val)
{
return __sync_fetch_and_sub((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_sub32(StgWord x, StgWord val);
-StgWord
-hs_atomic_sub32(StgWord x, StgWord val)
+StgWord hs_atomic_sub32(StgWord x, StgWord val)
{
return __sync_fetch_and_sub((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_sub64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_sub64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_sub64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_sub((volatile StgWord64 *) x, val);
}
// FetchAndByteArrayOp_Int
-extern StgWord hs_atomic_and8(StgWord x, StgWord val);
-StgWord
-hs_atomic_and8(StgWord x, StgWord val)
+StgWord hs_atomic_and8(StgWord x, StgWord val)
{
return __sync_fetch_and_and((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_and16(StgWord x, StgWord val);
-StgWord
-hs_atomic_and16(StgWord x, StgWord val)
+StgWord hs_atomic_and16(StgWord x, StgWord val)
{
return __sync_fetch_and_and((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_and32(StgWord x, StgWord val);
-StgWord
-hs_atomic_and32(StgWord x, StgWord val)
+StgWord hs_atomic_and32(StgWord x, StgWord val)
{
return __sync_fetch_and_and((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_and64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_and64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_and64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_and((volatile StgWord64 *) x, val);
}
@@ -167,9 +143,7 @@ hs_atomic_and64(StgWord x, StgWord64 val)
#pragma GCC diagnostic ignored "-Wsync-nand"
#endif
-extern StgWord hs_atomic_nand8(StgWord x, StgWord val);
-StgWord
-hs_atomic_nand8(StgWord x, StgWord val)
+StgWord hs_atomic_nand8(StgWord x, StgWord val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord8 *) x, (StgWord8) val);
@@ -178,9 +152,7 @@ hs_atomic_nand8(StgWord x, StgWord val)
#endif
}
-extern StgWord hs_atomic_nand16(StgWord x, StgWord val);
-StgWord
-hs_atomic_nand16(StgWord x, StgWord val)
+StgWord hs_atomic_nand16(StgWord x, StgWord val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord16 *) x, (StgWord16) val);
@@ -189,9 +161,7 @@ hs_atomic_nand16(StgWord x, StgWord val)
#endif
}
-extern StgWord hs_atomic_nand32(StgWord x, StgWord val);
-StgWord
-hs_atomic_nand32(StgWord x, StgWord val)
+StgWord hs_atomic_nand32(StgWord x, StgWord val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord32 *) x, (StgWord32) val);
@@ -200,9 +170,7 @@ hs_atomic_nand32(StgWord x, StgWord val)
#endif
}
-extern StgWord64 hs_atomic_nand64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_nand64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_nand64(StgWord x, StgWord64 val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord64 *) x, val);
@@ -215,96 +183,72 @@ hs_atomic_nand64(StgWord x, StgWord64 val)
// FetchOrByteArrayOp_Int
-extern StgWord hs_atomic_or8(StgWord x, StgWord val);
-StgWord
-hs_atomic_or8(StgWord x, StgWord val)
+StgWord hs_atomic_or8(StgWord x, StgWord val)
{
return __sync_fetch_and_or((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_or16(StgWord x, StgWord val);
-StgWord
-hs_atomic_or16(StgWord x, StgWord val)
+StgWord hs_atomic_or16(StgWord x, StgWord val)
{
return __sync_fetch_and_or((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_or32(StgWord x, StgWord val);
-StgWord
-hs_atomic_or32(StgWord x, StgWord val)
+StgWord hs_atomic_or32(StgWord x, StgWord val)
{
return __sync_fetch_and_or((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_or64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_or64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_or64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_or((volatile StgWord64 *) x, val);
}
// FetchXorByteArrayOp_Int
-extern StgWord hs_atomic_xor8(StgWord x, StgWord val);
-StgWord
-hs_atomic_xor8(StgWord x, StgWord val)
+StgWord hs_atomic_xor8(StgWord x, StgWord val)
{
return __sync_fetch_and_xor((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_xor16(StgWord x, StgWord val);
-StgWord
-hs_atomic_xor16(StgWord x, StgWord val)
+StgWord hs_atomic_xor16(StgWord x, StgWord val)
{
return __sync_fetch_and_xor((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_xor32(StgWord x, StgWord val);
-StgWord
-hs_atomic_xor32(StgWord x, StgWord val)
+StgWord hs_atomic_xor32(StgWord x, StgWord val)
{
return __sync_fetch_and_xor((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_xor64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_xor64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_xor64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_xor((volatile StgWord64 *) x, val);
}
// CasByteArrayOp_Int
-extern StgWord hs_cmpxchg8(StgWord x, StgWord old, StgWord new);
-StgWord
-hs_cmpxchg8(StgWord x, StgWord old, StgWord new)
+StgWord hs_cmpxchg8(StgWord x, StgWord old, StgWord new)
{
StgWord8 expected = (StgWord8) old;
__atomic_compare_exchange_n((StgWord8 *) x, &expected, (StgWord8) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
-extern StgWord hs_cmpxchg16(StgWord x, StgWord old, StgWord new);
-StgWord
-hs_cmpxchg16(StgWord x, StgWord old, StgWord new)
+StgWord hs_cmpxchg16(StgWord x, StgWord old, StgWord new)
{
StgWord16 expected = (StgWord16) old;
__atomic_compare_exchange_n((StgWord16 *) x, &expected, (StgWord16) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
-extern StgWord hs_cmpxchg32(StgWord x, StgWord old, StgWord new);
-StgWord
-hs_cmpxchg32(StgWord x, StgWord old, StgWord new)
+StgWord hs_cmpxchg32(StgWord x, StgWord old, StgWord new)
{
StgWord32 expected = (StgWord32) old;
__atomic_compare_exchange_n((StgWord32 *) x, &expected, (StgWord32) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
-extern StgWord64 hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new);
-StgWord64
-hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new)
+StgWord64 hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new)
{
StgWord64 expected = (StgWord64) old;
__atomic_compare_exchange_n((StgWord64 *) x, &expected, (StgWord64) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
@@ -313,31 +257,23 @@ hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new)
// Atomic exchange operations
-extern StgWord hs_xchg8(StgWord x, StgWord val);
-StgWord
-hs_xchg8(StgWord x, StgWord val)
+StgWord hs_xchg8(StgWord x, StgWord val)
{
return (StgWord) __atomic_exchange_n((StgWord8 *) x, (StgWord8) val, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_xchg16(StgWord x, StgWord val);
-StgWord
-hs_xchg16(StgWord x, StgWord val)
+StgWord hs_xchg16(StgWord x, StgWord val)
{
return (StgWord) __atomic_exchange_n((StgWord16 *)x, (StgWord16) val, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_xchg32(StgWord x, StgWord val);
-StgWord
-hs_xchg32(StgWord x, StgWord val)
+StgWord hs_xchg32(StgWord x, StgWord val)
{
return (StgWord) __atomic_exchange_n((StgWord32 *) x, (StgWord32) val, __ATOMIC_SEQ_CST);
}
//GCC provides this even on 32bit, but StgWord is still 32 bits.
-extern StgWord64 hs_xchg64(StgWord x, StgWord64 val);
-StgWord64
-hs_xchg64(StgWord x, StgWord64 val)
+StgWord64 hs_xchg64(StgWord x, StgWord64 val)
{
return (StgWord64) __atomic_exchange_n((StgWord64 *) x, (StgWord64) val, __ATOMIC_SEQ_CST);
}
@@ -352,30 +288,22 @@ hs_xchg64(StgWord x, StgWord64 val)
// primitives which the GCC documentation claims "usually" implies a full
// barrier.
-extern StgWord hs_atomicread8(StgWord x);
-StgWord
-hs_atomicread8(StgWord x)
+StgWord hs_atomicread8(StgWord x)
{
return __atomic_load_n((StgWord8 *) x, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_atomicread16(StgWord x);
-StgWord
-hs_atomicread16(StgWord x)
+StgWord hs_atomicread16(StgWord x)
{
return __atomic_load_n((StgWord16 *) x, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_atomicread32(StgWord x);
-StgWord
-hs_atomicread32(StgWord x)
+StgWord hs_atomicread32(StgWord x)
{
return __atomic_load_n((StgWord32 *) x, __ATOMIC_SEQ_CST);
}
-extern StgWord64 hs_atomicread64(StgWord x);
-StgWord64
-hs_atomicread64(StgWord x)
+StgWord64 hs_atomicread64(StgWord x)
{
return __atomic_load_n((StgWord64 *) x, __ATOMIC_SEQ_CST);
}
@@ -384,30 +312,22 @@ hs_atomicread64(StgWord x)
// Implies a full memory barrier (see compiler/GHC/Builtin/primops.txt.pp)
// __ATOMIC_SEQ_CST: Full barrier (see hs_atomicread8 above).
-extern void hs_atomicwrite8(StgWord x, StgWord val);
-void
-hs_atomicwrite8(StgWord x, StgWord val)
+void hs_atomicwrite8(StgWord x, StgWord val)
{
__atomic_store_n((StgWord8 *) x, (StgWord8) val, __ATOMIC_SEQ_CST);
}
-extern void hs_atomicwrite16(StgWord x, StgWord val);
-void
-hs_atomicwrite16(StgWord x, StgWord val)
+void hs_atomicwrite16(StgWord x, StgWord val)
{
__atomic_store_n((StgWord16 *) x, (StgWord16) val, __ATOMIC_SEQ_CST);
}
-extern void hs_atomicwrite32(StgWord x, StgWord val);
-void
-hs_atomicwrite32(StgWord x, StgWord val)
+void hs_atomicwrite32(StgWord x, StgWord val)
{
__atomic_store_n((StgWord32 *) x, (StgWord32) val, __ATOMIC_SEQ_CST);
}
-extern void hs_atomicwrite64(StgWord x, StgWord64 val);
-void
-hs_atomicwrite64(StgWord x, StgWord64 val)
+void hs_atomicwrite64(StgWord x, StgWord64 val)
{
__atomic_store_n((StgWord64 *) x, (StgWord64) val, __ATOMIC_SEQ_CST);
}
=====================================
libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
=====================================
=====================================
libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
=====================================
=====================================
libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
=====================================
=====================================
libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
=====================================
=====================================
libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
=====================================
=====================================
libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
=====================================
=====================================
libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
=====================================
=====================================
libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
=====================================
=====================================
libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
=====================================
=====================================
libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
=====================================
=====================================
libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
=====================================
=====================================
libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
=====================================
=====================================
rts/rts.cabal
=====================================
@@ -529,6 +529,19 @@ library
sm/Storage.c
sm/Sweep.c
fs.c
+ prim/atomic.c
+ prim/bitrev.c
+ prim/bswap.c
+ prim/clz.c
+ prim/ctz.c
+ prim/int64x2minmax.c
+ prim/longlong.c
+ prim/mulIntMayOflo.c
+ prim/pdep.c
+ prim/pext.c
+ prim/popcnt.c
+ prim/vectorQuotRem.c
+ prim/word2float.c
-- I wish we had wildcards..., this would be:
-- *.c hooks/**/*.c sm/**/*.c eventlog/**/*.c linker/**/*.c
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/480471cc326c4ad3e15bdf6b8e50e10…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/480471cc326c4ad3e15bdf6b8e50e10…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T26166] 2 commits: Move code-gen aux symbols from ghc-internal to rts
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
10 Oct '25
Rodrigo Mesquita pushed to branch wip/T26166 at Glasgow Haskell Compiler / GHC
Commits:
480471cc by Rodrigo Mesquita at 2025-10-10T14:58:21+01:00
Move code-gen aux symbols from ghc-internal to rts
These symbols were all previously defined in ghc-internal and made the
dependency structure awkward, where the rts may refer to some of these
symbols and had to work around that circular dependency the way
described in #26166.
Moreover, the code generator will produce code that uses these symbols!
Therefore, they should be available in the rts:
PRINCIPLE: If the code generator may produce code which uses this
symbol, then it should be defined in the rts rather than, say,
ghc-internal.
That said, the main motivation is towards fixing #26166.
Towards #26166. Pre-requisite of !14892
- - - - -
b2a6c0b9 by Ben Gamari at 2025-10-10T14:58:21+01:00
rts: Avoid static symbol references to ghc-internal
This resolves #26166, a bug due to new constraints placed by Apple's
linker on undefined references.
One source of such references in the RTS is the many symbols referenced
in ghc-internal. To mitigate #26166, we make these references dynamic,
as described in Note [RTS/ghc-internal interface].
Fixes #26166
Co-authored-by: Rodrigo Mesquita <rodrigo.m.mesquita(a)gmail.com>
- - - - -
45 changed files:
- compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/Linker/Dynamic.hs
- compiler/GHC/Linker/Static.hs
- hadrian/src/Settings/Packages.hs
- + libraries/ghc-internal/cbits/RtsIface.c
- libraries/ghc-internal/ghc-internal.cabal.in
- + libraries/ghc-internal/include/RtsIfaceSymbols.h
- rts/BuiltinClosures.c
- rts/CloneStack.h
- rts/Compact.cmm
- rts/ContinuationOps.cmm
- rts/Exception.cmm
- rts/Prelude.h
- rts/PrimOps.cmm
- rts/RtsAPI.c
- rts/RtsStartup.c
- rts/RtsSymbols.c
- + rts/RtsToHsIface.c
- rts/Schedule.c
- rts/StgStdThunks.cmm
- rts/configure.ac
- − rts/external-symbols.list.in
- rts/include/Rts.h
- rts/include/RtsAPI.h
- + rts/include/rts/RtsToHsIface.h
- rts/include/stg/Prim.h
- rts/posix/Signals.c
- libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
- libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
- libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
- libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
- libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
- libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
- libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
- libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
- libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
- libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
- libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
- libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
- libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
- − rts/rts.buildinfo.in
- rts/rts.cabal
- rts/wasm/JSFFI.c
- utils/deriveConstants/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3d6f1bfc305187aa44cd21591f49aa…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/3d6f1bfc305187aa44cd21591f49aa…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T26166] 2 commits: Move code-gen aux symbols from ghc-internal to rts
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
10 Oct '25
Rodrigo Mesquita pushed to branch wip/T26166 at Glasgow Haskell Compiler / GHC
Commits:
2e1c436e by Rodrigo Mesquita at 2025-10-10T14:33:06+01:00
Move code-gen aux symbols from ghc-internal to rts
These symbols were all previously defined in ghc-internal and made the
dependency structure awkward, where the rts may refer to some of these
symbols and had to work around that circular dependency the way
described in #26166.
Moreover, the code generator will produce code that uses these symbols!
Therefore, they should be available in the rts:
PRINCIPLE: If the code generator may produce code which uses this
symbol, then it should be defined in the rts rather than, say,
ghc-internal.
That said, the main motivation is towards fixing #26166.
Towards #26166. Pre-requisite of !14892
- - - - -
3d6f1bfc by Ben Gamari at 2025-10-10T14:33:06+01:00
rts: Avoid static symbol references to ghc-internal
This resolves #26166, a bug due to new constraints placed by Apple's
linker on undefined references.
One source of such references in the RTS is the many symbols referenced
in ghc-internal. To mitigate #26166, we make these references dynamic,
as described in Note [RTS/ghc-internal interface].
Fixes #26166
Co-authored-by: Rodrigo Mesquita <rodrigo.m.mesquita(a)gmail.com>
- - - - -
44 changed files:
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/Linker/Dynamic.hs
- compiler/GHC/Linker/Static.hs
- hadrian/src/Settings/Packages.hs
- + libraries/ghc-internal/cbits/RtsIface.c
- libraries/ghc-internal/ghc-internal.cabal.in
- + libraries/ghc-internal/include/RtsIfaceSymbols.h
- rts/BuiltinClosures.c
- rts/CloneStack.h
- rts/Compact.cmm
- rts/ContinuationOps.cmm
- rts/Exception.cmm
- rts/Prelude.h
- rts/PrimOps.cmm
- rts/RtsAPI.c
- rts/RtsStartup.c
- rts/RtsSymbols.c
- + rts/RtsToHsIface.c
- rts/Schedule.c
- rts/StgStdThunks.cmm
- rts/configure.ac
- − rts/external-symbols.list.in
- rts/include/Rts.h
- rts/include/RtsAPI.h
- + rts/include/rts/RtsToHsIface.h
- rts/include/stg/Prim.h
- rts/posix/Signals.c
- libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
- libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
- libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
- libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
- libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
- libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
- libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
- libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
- libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
- libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
- libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
- libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
- libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
- − rts/rts.buildinfo.in
- rts/rts.cabal
- rts/wasm/JSFFI.c
- utils/deriveConstants/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/03f6b9307fcb22620789e6b333f043…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/03f6b9307fcb22620789e6b333f043…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T26166] 2 commits: Move code-gen aux symbols from ghc-internal to rts
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
10 Oct '25
Rodrigo Mesquita pushed to branch wip/T26166 at Glasgow Haskell Compiler / GHC
Commits:
35ea01fa by Rodrigo Mesquita at 2025-10-10T14:25:05+01:00
Move code-gen aux symbols from ghc-internal to rts
These symbols were all previously defined in ghc-internal and made the
dependency structure awkward, where the rts may refer to some of these
symbols and had to work around that circular dependency the way
described in #26166.
Moreover, the code generator will produce code that uses these symbols!
Therefore, they should be available in the rts:
PRINCIPLE: If the code generator may produce code which uses this
symbol, then it should be defined in the rts rather than, say,
ghc-internal.
That said, the main motivation is towards fixing #26166.
Towards #26166. Pre-requisite of !14892
- - - - -
03f6b930 by Ben Gamari at 2025-10-10T14:25:05+01:00
rts: Avoid static symbol references to ghc-internal
This resolves #26166, a bug due to new constraints placed by Apple's
linker on undefined references.
One source of such references in the RTS is the many symbols referenced
in ghc-internal. To mitigate #26166, we make these references dynamic,
as described in Note [RTS/ghc-internal interface].
Fixes #26166
Co-authored-by: Rodrigo Mesquita <rodrigo.m.mesquita(a)gmail.com>
- - - - -
44 changed files:
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/Linker/Dynamic.hs
- compiler/GHC/Linker/Static.hs
- hadrian/src/Settings/Packages.hs
- + libraries/ghc-internal/cbits/RtsIface.c
- libraries/ghc-internal/ghc-internal.cabal.in
- + libraries/ghc-internal/include/RtsIfaceSymbols.h
- rts/BuiltinClosures.c
- rts/CloneStack.h
- rts/Compact.cmm
- rts/ContinuationOps.cmm
- rts/Exception.cmm
- rts/Prelude.h
- rts/PrimOps.cmm
- rts/RtsAPI.c
- rts/RtsStartup.c
- rts/RtsSymbols.c
- + rts/RtsToHsIface.c
- rts/Schedule.c
- rts/StgStdThunks.cmm
- rts/configure.ac
- − rts/external-symbols.list.in
- rts/include/Rts.h
- rts/include/RtsAPI.h
- + rts/include/rts/RtsToHsIface.h
- rts/include/stg/Prim.h
- rts/posix/Signals.c
- libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
- libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
- libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
- libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
- libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
- libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
- libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
- libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
- libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
- libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
- libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
- libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
- libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
- − rts/rts.buildinfo.in
- rts/rts.cabal
- rts/wasm/JSFFI.c
- utils/deriveConstants/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0a23708b6283c6e46dadb3d94e83b1…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/0a23708b6283c6e46dadb3d94e83b1…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T26166] 2 commits: Move code-gen aux symbols from ghc-internal to rts
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
10 Oct '25
Rodrigo Mesquita pushed to branch wip/T26166 at Glasgow Haskell Compiler / GHC
Commits:
1e62b9c9 by Rodrigo Mesquita at 2025-10-10T13:34:53+01:00
Move code-gen aux symbols from ghc-internal to rts
These symbols were all previously defined in ghc-internal and made the
dependency structure awkward, where the rts may refer to some of these
symbols and had to work around that circular dependency the way
described in #26166.
Moreover, the code generator will produce code that uses these symbols!
Therefore, they should be available in the rts:
PRINCIPLE: If the code generator may produce code which uses this
symbol, then it should be defined in the rts rather than, say,
ghc-internal.
That said, the main motivation is towards fixing #26166.
Towards #26166. Pre-requisite of !14892
- - - - -
0a23708b by Ben Gamari at 2025-10-10T14:23:37+01:00
rts: Avoid static symbol references to ghc-internal
This resolves #26166, a bug due to new constraints placed by Apple's
linker on undefined references.
One source of such references in the RTS is the many symbols referenced
in ghc-internal. To mitigate #26166, we make these references dynamic,
as described in Note [RTS/ghc-internal interface].
Fixes #26166
Co-authored-by: Rodrigo Mesquita <rodrigo.m.mesquita(a)gmail.com>
- - - - -
44 changed files:
- compiler/GHC/HsToCore/Foreign/C.hs
- compiler/GHC/Linker/Dynamic.hs
- compiler/GHC/Linker/Static.hs
- hadrian/src/Settings/Packages.hs
- + libraries/ghc-internal/cbits/RtsIface.c
- libraries/ghc-internal/ghc-internal.cabal.in
- + libraries/ghc-internal/include/RtsIfaceSymbols.h
- rts/BuiltinClosures.c
- rts/CloneStack.h
- rts/Compact.cmm
- rts/ContinuationOps.cmm
- rts/Exception.cmm
- rts/Prelude.h
- rts/PrimOps.cmm
- rts/RtsAPI.c
- rts/RtsStartup.c
- rts/RtsSymbols.c
- + rts/RtsToHsIface.c
- rts/Schedule.c
- rts/StgStdThunks.cmm
- rts/configure.ac
- − rts/external-symbols.list.in
- rts/include/Rts.h
- rts/include/RtsAPI.h
- + rts/include/rts/RtsToHsIface.h
- rts/include/stg/Prim.h
- rts/posix/Signals.c
- libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
- libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
- libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
- libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
- libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
- libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
- libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
- libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
- libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
- libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
- libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
- libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
- libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
- − rts/rts.buildinfo.in
- rts/rts.cabal
- rts/wasm/JSFFI.c
- utils/deriveConstants/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b58f7922b5ea74aa60854dcf329b2c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/b58f7922b5ea74aa60854dcf329b2c…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/gbc-files] 13 commits: Add a perf test for #26425
by Matthew Pickering (@mpickering) 10 Oct '25
by Matthew Pickering (@mpickering) 10 Oct '25
10 Oct '25
Matthew Pickering pushed to branch wip/gbc-files at Glasgow Haskell Compiler / GHC
Commits:
41bdb16f by Andreas Klebinger at 2025-10-06T18:04:34-04:00
Add a perf test for #26425
- - - - -
1da0c700 by Andreas Klebinger at 2025-10-06T18:05:14-04:00
Testsuite: Silence warnings about Wx-partial in concprog001
- - - - -
7471eb6a by sheaf at 2025-10-07T21:39:43-04:00
Improve how we detect user type errors in types
This commit cleans up all the code responsible for detecting whether a
type contains "TypeError msg" applications nested inside it. All the
logic is now in 'userTypeError_maybe', which is always deep. Whether
it looks inside type family applications is determined by the passed-in
boolean flag:
- When deciding whether a constraint is definitely insoluble, don't
look inside type family applications, as they may still reduce -- in
which case the TypeError could disappear.
- When reporting unsolved constraints, look inside type family
applications: they had the chance to reduce but didn't, and the
custom type error might contain valuable information.
All the details are explained in Note [Custom type errors in constraints]
in GHC.Tc.Types.Constraint.
Another benefit of this change is that it allows us to get rid of the
deeply dodgy 'getUserTypeErrorMsg' function.
This commit also improves the detection of custom type errors, for
example in equality constraints:
TypeError blah ~# rhs
It used to be the case that we didn't detect the TypeError on the LHS,
because we never considered that equality constraints could be insoluble
due to the presence of custom type errors. Addressing this oversight
improves detection of redundant pattern match warnings, fixing #26400.
- - - - -
29955267 by Rodrigo Mesquita at 2025-10-07T21:40:25-04:00
cleanup: Drop obsolete settings from config.mk.in
These values used to be spliced into the bindist's `config.mk` s.t. when
`make` was run, the values were read and written into the bindist installation `settings` file.
However, we now carry these values to the bindist directly in the
default.target toolchain file, and `make` writes almost nothing to
`settings` now (see #26227)
The entries deleted in this MR were already unused.
Fixes #26478
- - - - -
f7adfed2 by ARATA Mizuki at 2025-10-08T08:37:24-04:00
T22033 is only relevant if the word size is 64-bit
Fixes #25497
- - - - -
ff1650c9 by Ben Gamari at 2025-10-08T08:38:07-04:00
rts/posix: Enforce iteration limit on heap reservation logic
Previously we could loop indefinitely when attempting to get an address
space reservation for our heap. Limit the logic to 8 iterations to
ensure we instead issue a reasonable error message.
Addresses #26151.
- - - - -
01844557 by Ben Gamari at 2025-10-08T08:38:07-04:00
rts/posix: Hold on to low reservations when reserving heap
Previously when the OS gave us an address space reservation in low
memory we would immediately release it and try again. However, on some
platforms this meant that we would get the same allocation again in the
next iteration (since mmap's `hint` argument is just that, a hint).
Instead we now hold on to low reservations until we have found a
suitable heap reservation.
Fixes #26151.
- - - - -
b2c8d052 by Sven Tennie at 2025-10-08T08:38:47-04:00
Build terminfo only in upper stages in cross-builds (#26288)
Currently, there's no way to provide library paths for [n]curses for
both - build and target - in cross-builds. As stage0 is only used to
build upper stages, it should be fine to build terminfo only for them.
This re-enables building cross-compilers with terminfo.
- - - - -
c58f9a61 by Julian Ospald at 2025-10-08T08:39:36-04:00
ghc-toolchain: Drop `ld.gold` from merge object command
It's deprecated.
Also see #25716
- - - - -
2b8baada by sheaf at 2025-10-08T18:23:37-04:00
Improvements to 'mayLookIdentical'
This commit makes significant improvements to the machinery that decides
when we should pretty-print the "invisible bits" of a type, such as:
- kind applications, e.g. '@k' in 'Proxy @k ty'
- RuntimeReps, e.g. 'TYPE r'
- multiplicities and linear arrows 'a %1 -> b'
To do this, this commit refactors 'mayLookIdentical' to return **which**
of the invisible bits don't match up, e.g. in
(a %1 -> b) ~ (a %Many -> b)
we find that the invisible bit that doesn't match up is a multiplicity,
so we should set 'sdocLinearTypes = True' when pretty-printing, and with
e.g.
Proxy @k1 ~ Proxy @k2
we find that the invisible bit that doesn't match up is an invisible
TyCon argument, so we set 'sdocPrintExplicitKinds = True'.
We leverage these changes to remove the ad-hoc treatment of linearity
of data constructors with 'dataConDisplayType' and 'dataConNonLinearType'.
This is now handled by the machinery of 'pprWithInvisibleBits'.
Fixes #26335 #26340
- - - - -
129ce32d by sheaf at 2025-10-08T18:23:37-04:00
Store SDoc context in SourceError
This commits modifies the SourceError datatype which is used for
throwing and then reporting exceptions by storing all the info we need
to be able to print the SDoc, including whether we should print with
explicit kinds, explicit runtime-reps, etc.
This is done using the new datatype:
data SourceErrorContext
= SEC
!DiagOpts
!(DiagnosticOpts GhcMessage)
Now, when we come to report an error (by handling the exception), we
have access to the full context we need.
Fixes #26387
- - - - -
f9790ca8 by Ben Gamari at 2025-10-08T18:24:19-04:00
gitlab-ci: Make RELEASE_JOB an input
Rather than an undocumented variable.
- - - - -
e689e516 by Matthew Pickering at 2025-10-10T09:44:34+01:00
Add support for generating bytecode objects
This commit adds the `-fwrite-byte-code` option which makes GHC emit a
`.gbc` file which contains a serialised representation of bytecode.
The bytecode can be loaded by the compiler to avoid having to
reinterpret a module when using the bytecode interpreter (for example,
in GHCi).
There are also the new options:
* -gbcdir=<DIR>: Specify the directory to place the gbc files
* -gbcsuf=<suffix>: Specify the suffix for gbc files
The option `-fbyte-code-and-object-code` now implies
`-fwrite-byte-code`.
These performance tests fail due to https://github.com/haskell/directory/issues/204
-------------------------
Metric Increase:
MultiComponentModules
MultiLayerModules
MultiComponentModulesRecomp
MultiLayerModulesRecomp
MultiLayerModulesTH_Make
MultiLayerModulesTH_OneShot
T13701
-------------------------
The bytecode serialisation part was implemented by Cheng Shao
Co-authored-by: Cheng Shao <terrorjack(a)type.dance>
- - - - -
155 changed files:
- .gitlab-ci.yml
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- compiler/GHC.hs
- compiler/GHC/Builtin/PrimOps.hs
- compiler/GHC/ByteCode/Breakpoints.hs
- + compiler/GHC/ByteCode/Serialize.hs
- compiler/GHC/ByteCode/Types.hs
- compiler/GHC/Core/Multiplicity.hs
- compiler/GHC/Core/Predicate.hs
- compiler/GHC/Core/TyCo/Compare.hs
- compiler/GHC/Core/TyCo/Ppr.hs
- compiler/GHC/Core/Type.hs
- compiler/GHC/Data/FlatBag.hs
- compiler/GHC/Data/SmallArray.hs
- compiler/GHC/Driver/Backend.hs
- compiler/GHC/Driver/Backpack.hs
- + compiler/GHC/Driver/ByteCode.hs
- compiler/GHC/Driver/Config/Finder.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Env/Types.hs
- compiler/GHC/Driver/Errors.hs
- compiler/GHC/Driver/Flags.hs
- compiler/GHC/Driver/Main.hs
- compiler/GHC/Driver/Make.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Messager.hs
- compiler/GHC/Driver/Monad.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Type.hs
- compiler/GHC/HsToCore/Breakpoints.hs
- compiler/GHC/HsToCore/Usage.hs
- compiler/GHC/Iface/Decl.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Load.hs
- compiler/GHC/Iface/Make.hs
- compiler/GHC/Iface/Type.hs
- compiler/GHC/Linker/Deps.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Types.hs
- compiler/GHC/Parser/Header.hs
- compiler/GHC/Runtime/Eval.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/HsType.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Solve.hs
- compiler/GHC/Tc/TyCl.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/CtLoc.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/TcMType.hs
- compiler/GHC/Tc/Utils/TcType.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Utils/Unify.hs-boot
- compiler/GHC/Tc/Validity.hs
- compiler/GHC/Types/SourceError.hs
- compiler/GHC/Types/SptEntry.hs
- compiler/GHC/Types/Tickish.hs
- compiler/GHC/Types/TyThing/Ppr.hs
- compiler/GHC/Unit/Finder.hs
- compiler/GHC/Unit/Finder/Types.hs
- compiler/GHC/Unit/Module/Graph.hs
- compiler/GHC/Unit/Module/Location.hs
- compiler/GHC/Unit/Module/ModSummary.hs
- compiler/GHC/Unit/Module/WholeCoreBindings.hs
- compiler/GHC/Utils/Binary.hs
- compiler/GHC/Utils/Error.hs
- compiler/GHC/Utils/Outputable.hs
- compiler/ghc.cabal.in
- docs/users_guide/phases.rst
- docs/users_guide/separate_compilation.rst
- ghc/GHCi/UI.hs
- hadrian/bindist/config.mk.in
- hadrian/src/Settings/Default.hs
- rts/posix/OSMem.c
- testsuite/tests/bytecode/T24634/T24634a.stdout
- testsuite/tests/bytecode/T24634/T24634b.stdout
- testsuite/tests/concurrent/prog001/all.T
- testsuite/tests/count-deps/CountDepsAst.stdout
- testsuite/tests/count-deps/CountDepsParser.stdout
- testsuite/tests/cpranal/should_compile/T18174.stderr
- testsuite/tests/driver/T11429c.stderr
- testsuite/tests/driver/T21682.stderr
- + testsuite/tests/driver/bytecode-object/A.hs
- + testsuite/tests/driver/bytecode-object/BytecodeForeign.c
- + testsuite/tests/driver/bytecode-object/BytecodeForeign.hs
- + testsuite/tests/driver/bytecode-object/BytecodeMain.hs
- + testsuite/tests/driver/bytecode-object/BytecodeTest.hs
- + testsuite/tests/driver/bytecode-object/Makefile
- + testsuite/tests/driver/bytecode-object/all.T
- + testsuite/tests/driver/bytecode-object/bytecode_object12.stderr
- + testsuite/tests/driver/bytecode-object/bytecode_object13.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object14.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object15.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object16.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object17.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object18.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object19.script
- + testsuite/tests/driver/bytecode-object/bytecode_object19.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object25.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object4.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object5.stdout
- + testsuite/tests/driver/bytecode-object/bytecode_object6.stdout
- testsuite/tests/driver/fat-iface/T22405/T22405.stdout
- testsuite/tests/driver/fat-iface/T22405/T22405b.stdout
- testsuite/tests/driver/fat-iface/fat011.stderr
- testsuite/tests/ghc-api/T10942.hs
- testsuite/tests/ghc-api/annotations-literals/literals.hs
- testsuite/tests/indexed-types/should_fail/T14887.stderr
- testsuite/tests/linear/should_fail/T19361.stderr
- testsuite/tests/llvm/should_run/all.T
- testsuite/tests/perf/compiler/Makefile
- + testsuite/tests/perf/compiler/MultiLayerModulesDefsGhciWithBytecodeFiles.script
- + testsuite/tests/perf/compiler/T26425.hs
- testsuite/tests/perf/compiler/all.T
- + testsuite/tests/pmcheck/should_compile/T26400.hs
- + testsuite/tests/pmcheck/should_compile/T26400.stderr
- + testsuite/tests/pmcheck/should_compile/T26400b.hs
- testsuite/tests/pmcheck/should_compile/all.T
- testsuite/tests/roles/should_compile/Roles13.stderr
- testsuite/tests/simplCore/should_compile/OpaqueNoCastWW.stderr
- testsuite/tests/simplCore/should_compile/T17673.stderr
- testsuite/tests/simplCore/should_compile/T18078.stderr
- testsuite/tests/simplCore/should_compile/T18995.stderr
- testsuite/tests/simplCore/should_compile/T19890.stderr
- testsuite/tests/simplCore/should_compile/T21948.stderr
- testsuite/tests/simplCore/should_compile/T21960.stderr
- testsuite/tests/simplCore/should_compile/T24808.stderr
- − testsuite/tests/simplCore/should_compile/T25713.stderr
- testsuite/tests/simplCore/should_compile/T4201.stdout
- testsuite/tests/simplCore/should_compile/T8331.stderr
- testsuite/tests/simplStg/should_compile/T22840.stderr
- testsuite/tests/typecheck/no_skolem_info/T20232.stderr
- testsuite/tests/typecheck/should_fail/T11672.stderr
- testsuite/tests/typecheck/should_fail/T12373.stderr
- testsuite/tests/typecheck/should_fail/T15807.stderr
- testsuite/tests/typecheck/should_fail/T16074.stderr
- testsuite/tests/typecheck/should_fail/T18357a.stderr
- testsuite/tests/typecheck/should_fail/T19627.stderr
- testsuite/tests/typecheck/should_fail/T20241b.stderr
- testsuite/tests/typecheck/should_fail/T21530a.stderr
- testsuite/tests/typecheck/should_fail/UnliftedNewtypesFamilyKindFail2.stderr
- testsuite/tests/typecheck/should_fail/VisFlag1.stderr
- utils/check-exact/Parsers.hs
- utils/check-exact/Preprocess.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/MergeObjs.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c7f8f69f6f541308e148a9e9f04505…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/c7f8f69f6f541308e148a9e9f04505…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/26166-move-prims] Move code-gen aux symbols from ghc-internal to rts
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
by Rodrigo Mesquita (@alt-romes) 10 Oct '25
10 Oct '25
Rodrigo Mesquita pushed to branch wip/romes/26166-move-prims at Glasgow Haskell Compiler / GHC
Commits:
1e62b9c9 by Rodrigo Mesquita at 2025-10-10T13:34:53+01:00
Move code-gen aux symbols from ghc-internal to rts
These symbols were all previously defined in ghc-internal and made the
dependency structure awkward, where the rts may refer to some of these
symbols and had to work around that circular dependency the way
described in #26166.
Moreover, the code generator will produce code that uses these symbols!
Therefore, they should be available in the rts:
PRINCIPLE: If the code generator may produce code which uses this
symbol, then it should be defined in the rts rather than, say,
ghc-internal.
That said, the main motivation is towards fixing #26166.
Towards #26166. Pre-requisite of !14892
- - - - -
18 changed files:
- hadrian/src/Settings/Packages.hs
- libraries/ghc-internal/ghc-internal.cabal.in
- rts/RtsSymbols.c
- rts/include/stg/Prim.h
- libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
- libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
- libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
- libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
- libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
- libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
- libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
- libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
- libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
- libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
- libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
- libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
- libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
- rts/rts.cabal
Changes:
=====================================
hadrian/src/Settings/Packages.hs
=====================================
@@ -287,9 +287,6 @@ ghcInternalArgs = package ghcInternal ? do
, builder (Cabal Flags) ? flag NeedLibatomic `cabalFlag` "need-atomic"
- , builder (Cc CompileC) ? (not <$> flag CcLlvmBackend) ?
- input "**/cbits/atomic.c" ? arg "-Wno-sync-nand"
-
]
-- | RTS-specific command line arguments.
@@ -413,6 +410,9 @@ rtsPackageArgs = package rts ? do
, input "**/RetainerProfile.c" ? flag CcLlvmBackend ?
arg "-Wno-incompatible-pointer-types"
+
+ , input "**/prim/atomic.c" ? (not <$> flag CcLlvmBackend) ?
+ arg "-Wno-sync-nand"
]
mconcat
=====================================
libraries/ghc-internal/ghc-internal.cabal.in
=====================================
@@ -442,20 +442,7 @@ Library
cbits/sysconf.c
cbits/fs.c
cbits/strerror.c
- cbits/atomic.c
- cbits/bswap.c
- cbits/bitrev.c
- cbits/clz.c
- cbits/ctz.c
cbits/debug.c
- cbits/int64x2minmax.c
- cbits/longlong.c
- cbits/mulIntMayOflo.c
- cbits/pdep.c
- cbits/pext.c
- cbits/popcnt.c
- cbits/vectorQuotRem.c
- cbits/word2float.c
cbits/Stack_c.c
cmm-sources:
=====================================
rts/RtsSymbols.c
=====================================
@@ -1016,6 +1016,116 @@ extern char **environ;
#define RTS_FINI_ARRAY_SYMBOLS
#endif
+#define SymI_NeedsProtoAllSizes(symbol) \
+ SymI_NeedsProto(##symbol##8) \
+ SymI_NeedsProto(##symbol##16) \
+ SymI_NeedsProto(##symbol##32) \
+ SymI_NeedsProto(##symbol##64)
+
+#if !defined(arm_HOST_ARCH)
+#define RTS_ATOMICS_SYMBOLS \
+ SymI_NeedsProtoAllSizes(hs_atomic_add) \
+ SymI_NeedsProtoAllSizes(hs_atomic_sub) \
+ SymI_NeedsProtoAllSizes(hs_atomic_and) \
+ SymI_NeedsProtoAllSizes(hs_atomic_nand) \
+ SymI_NeedsProtoAllSizes(hs_atomic_or) \
+ SymI_NeedsProtoAllSizes(hs_atomic_xor) \
+ SymI_NeedsProtoAllSizes(hs_cmpxchg) \
+ SymI_NeedsProtoAllSizes(hs_xchg) \
+ SymI_NeedsProtoAllSizes(hs_atomicread) \
+ SymI_NeedsProtoAllSizes(hs_atomicwrite)
+#else
+// No atomics on arm32. See e9abcad4cc3
+#define RTS_ATOMICS_SYMBOLS
+#endif
+
+// In rts/longlong.c
+#if WORD_SIZE_IN_BITS < 64
+#define RTS_SYMBOLS_LONGLONG \
+ SymI_NeedsProto(hs_eq64) \
+ SymI_NeedsProto(hs_ne64) \
+ SymI_NeedsProto(hs_gtWord64) \
+ SymI_NeedsProto(hs_geWord64) \
+ SymI_NeedsProto(hs_ltWord64) \
+ SymI_NeedsProto(hs_leWord64) \
+ SymI_NeedsProto(hs_gtInt64) \
+ SymI_NeedsProto(hs_geInt64) \
+ SymI_NeedsProto(hs_ltInt64) \
+ SymI_NeedsProto(hs_leInt64) \
+ SymI_NeedsProto(hs_neg64) \
+ SymI_NeedsProto(hs_add64) \
+ SymI_NeedsProto(hs_sub64) \
+ SymI_NeedsProto(hs_mul64) \
+ SymI_NeedsProto(hs_remWord64) \
+ SymI_NeedsProto(hs_quotWord64) \
+ SymI_NeedsProto(hs_remInt64) \
+ SymI_NeedsProto(hs_quotInt64) \
+ SymI_NeedsProto(hs_and64) \
+ SymI_NeedsProto(hs_or64) \
+ SymI_NeedsProto(hs_xor64) \
+ SymI_NeedsProto(hs_not64) \
+ SymI_NeedsProto(hs_uncheckedShiftL64) \
+ SymI_NeedsProto(hs_uncheckedShiftRL64) \
+ SymI_NeedsProto(hs_uncheckedIShiftRA64) \
+ SymI_NeedsProto(hs_intToInt64) \
+ SymI_NeedsProto(hs_int64ToInt) \
+ SymI_NeedsProto(hs_wordToWord64) \
+ SymI_NeedsProto(hs_word64ToWord)
+#else
+#define RTS_SYMBOLS_LONGLONG
+#endif
+
+// rts/prim/vectorQuotRem.c and rts/prim/int64x2minmax
+#if defined(__SSE2__) \
+#define RTS_SYMBOLS_VECTORQUOTREM \
+ SymI_NeedsProto(hs_quotInt8X16) \
+ SymI_NeedsProto(hs_quotInt16X8) \
+ SymI_NeedsProto(hs_quotInt32X4) \
+ SymI_NeedsProto(hs_quotInt64X2) \
+ SymI_NeedsProto(hs_quotWord8X16) \
+ SymI_NeedsProto(hs_quotWord16X8) \
+ SymI_NeedsProto(hs_quotWord32X4) \
+ SymI_NeedsProto(hs_quotWord64X2) \
+ SymI_NeedsProto(hs_remInt8X16) \
+ SymI_NeedsProto(hs_remInt16X8) \
+ SymI_NeedsProto(hs_remInt32X4) \
+ SymI_NeedsProto(hs_remInt64X2) \
+ SymI_NeedsProto(hs_remWord8X16) \
+ SymI_NeedsProto(hs_remWord16X8) \
+ SymI_NeedsProto(hs_remWord32X4) \
+ SymI_NeedsProto(hs_remWord64X2)
+#define RTS_SYMBOLS_INT64X2MINMAX \
+ SymI_NeedsProto(hs_minInt64X2) \
+ SymI_NeedsProto(hs_maxInt64X2) \
+ SymI_NeedsProto(hs_minWord64X2) \
+ SymI_NeedsProto(hs_maxWord64X2)
+#else
+#define RTS_SYMBOLS_VECTORQUOTREM
+#define RTS_SYMBOLS_INT64X2MINMAX
+#endif
+
+// Symbols on files in rts/prim/*
+#define RTS_SYMBOLS_PRIM \
+ RTS_ATOMICS_SYMBOLS \
+ RTS_SYMBOLS_INT64X2MINMAX \
+ RTS_SYMBOLS_LONGLONG \
+ RTS_SYMBOLS_VECTORQUOTREM \
+ SymI_NeedsProtoAllSizes(hs_bitrev) \
+ SymI_NeedsProto(hs_bswap16) \
+ SymI_NeedsProto(hs_bswap32) \
+ SymI_NeedsProto(hs_bswap64) \
+ SymI_NeedsProtoAllSizes(hs_clz) \
+ SymI_NeedsProtoAllSizes(hs_ctz) \
+ SymI_NeedsProto(hs_mulIntMayOflo) \
+ SymI_NeedsProtoAllSizes(hs_pdep) \
+ SymI_NeedsProtoAllSizes(hs_pext) \
+ SymI_NeedsProtoAllSizes(hs_pext) \
+ SymI_NeedsProto(hs_popcnt) \
+ SymI_NeedsProtoAllSizes(hs_popcnt) \
+ SymI_NeedsProto(hs_word2float32) \
+ SymI_NeedsProto(hs_word2float64)
+
+
/* entirely bogus claims about types of these symbols */
#define SymI_NeedsProto(vvv) extern void vvv(void);
#define SymI_NeedsDataProto(vvv) extern StgWord vvv[];
@@ -1038,6 +1148,7 @@ RTS_ARCH_LIBGCC_SYMBOLS
RTS_FINI_ARRAY_SYMBOLS
RTS_LIBFFI_SYMBOLS
RTS_ARM_OUTLINE_ATOMIC_SYMBOLS
+RTS_SYMBOLS_PRIM
#undef SymI_NeedsProto
#undef SymI_NeedsDataProto
@@ -1081,6 +1192,7 @@ RtsSymbolVal rtsSyms[] = {
RTS_FINI_ARRAY_SYMBOLS
RTS_LIBFFI_SYMBOLS
RTS_ARM_OUTLINE_ATOMIC_SYMBOLS
+ RTS_SYMBOLS_PRIM
SymI_HasDataProto(nonmoving_write_barrier_enabled)
{ 0, 0, STRENGTH_NORMAL, SYM_TYPE_CODE } /* sentinel */
};
=====================================
rts/include/stg/Prim.h
=====================================
@@ -13,7 +13,7 @@
#pragma once
-/* libraries/ghc-internal/cbits/atomic.c */
+/* rts/prim/atomic.c */
StgWord hs_atomic_add8(StgWord x, StgWord val);
StgWord hs_atomic_add16(StgWord x, StgWord val);
StgWord hs_atomic_add32(StgWord x, StgWord val);
=====================================
libraries/ghc-internal/cbits/atomic.c → rts/prim/atomic.c
=====================================
@@ -12,90 +12,66 @@
// FetchAddByteArrayOp_Int
-extern StgWord hs_atomic_add8(StgWord x, StgWord val);
-StgWord
-hs_atomic_add8(StgWord x, StgWord val)
+StgWord hs_atomic_add8(StgWord x, StgWord val)
{
return __sync_fetch_and_add((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_add16(StgWord x, StgWord val);
-StgWord
-hs_atomic_add16(StgWord x, StgWord val)
+StgWord hs_atomic_add16(StgWord x, StgWord val)
{
return __sync_fetch_and_add((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_add32(StgWord x, StgWord val);
-StgWord
-hs_atomic_add32(StgWord x, StgWord val)
+StgWord hs_atomic_add32(StgWord x, StgWord val)
{
return __sync_fetch_and_add((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_add64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_add64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_add64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_add((volatile StgWord64 *) x, val);
}
// FetchSubByteArrayOp_Int
-extern StgWord hs_atomic_sub8(StgWord x, StgWord val);
-StgWord
-hs_atomic_sub8(StgWord x, StgWord val)
+StgWord hs_atomic_sub8(StgWord x, StgWord val)
{
return __sync_fetch_and_sub((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_sub16(StgWord x, StgWord val);
-StgWord
-hs_atomic_sub16(StgWord x, StgWord val)
+StgWord hs_atomic_sub16(StgWord x, StgWord val)
{
return __sync_fetch_and_sub((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_sub32(StgWord x, StgWord val);
-StgWord
-hs_atomic_sub32(StgWord x, StgWord val)
+StgWord hs_atomic_sub32(StgWord x, StgWord val)
{
return __sync_fetch_and_sub((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_sub64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_sub64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_sub64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_sub((volatile StgWord64 *) x, val);
}
// FetchAndByteArrayOp_Int
-extern StgWord hs_atomic_and8(StgWord x, StgWord val);
-StgWord
-hs_atomic_and8(StgWord x, StgWord val)
+StgWord hs_atomic_and8(StgWord x, StgWord val)
{
return __sync_fetch_and_and((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_and16(StgWord x, StgWord val);
-StgWord
-hs_atomic_and16(StgWord x, StgWord val)
+StgWord hs_atomic_and16(StgWord x, StgWord val)
{
return __sync_fetch_and_and((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_and32(StgWord x, StgWord val);
-StgWord
-hs_atomic_and32(StgWord x, StgWord val)
+StgWord hs_atomic_and32(StgWord x, StgWord val)
{
return __sync_fetch_and_and((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_and64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_and64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_and64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_and((volatile StgWord64 *) x, val);
}
@@ -167,9 +143,7 @@ hs_atomic_and64(StgWord x, StgWord64 val)
#pragma GCC diagnostic ignored "-Wsync-nand"
#endif
-extern StgWord hs_atomic_nand8(StgWord x, StgWord val);
-StgWord
-hs_atomic_nand8(StgWord x, StgWord val)
+StgWord hs_atomic_nand8(StgWord x, StgWord val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord8 *) x, (StgWord8) val);
@@ -178,9 +152,7 @@ hs_atomic_nand8(StgWord x, StgWord val)
#endif
}
-extern StgWord hs_atomic_nand16(StgWord x, StgWord val);
-StgWord
-hs_atomic_nand16(StgWord x, StgWord val)
+StgWord hs_atomic_nand16(StgWord x, StgWord val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord16 *) x, (StgWord16) val);
@@ -189,9 +161,7 @@ hs_atomic_nand16(StgWord x, StgWord val)
#endif
}
-extern StgWord hs_atomic_nand32(StgWord x, StgWord val);
-StgWord
-hs_atomic_nand32(StgWord x, StgWord val)
+StgWord hs_atomic_nand32(StgWord x, StgWord val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord32 *) x, (StgWord32) val);
@@ -200,9 +170,7 @@ hs_atomic_nand32(StgWord x, StgWord val)
#endif
}
-extern StgWord64 hs_atomic_nand64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_nand64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_nand64(StgWord x, StgWord64 val)
{
#if USE_SYNC_FETCH_AND_NAND
return __sync_fetch_and_nand((volatile StgWord64 *) x, val);
@@ -215,96 +183,72 @@ hs_atomic_nand64(StgWord x, StgWord64 val)
// FetchOrByteArrayOp_Int
-extern StgWord hs_atomic_or8(StgWord x, StgWord val);
-StgWord
-hs_atomic_or8(StgWord x, StgWord val)
+StgWord hs_atomic_or8(StgWord x, StgWord val)
{
return __sync_fetch_and_or((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_or16(StgWord x, StgWord val);
-StgWord
-hs_atomic_or16(StgWord x, StgWord val)
+StgWord hs_atomic_or16(StgWord x, StgWord val)
{
return __sync_fetch_and_or((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_or32(StgWord x, StgWord val);
-StgWord
-hs_atomic_or32(StgWord x, StgWord val)
+StgWord hs_atomic_or32(StgWord x, StgWord val)
{
return __sync_fetch_and_or((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_or64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_or64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_or64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_or((volatile StgWord64 *) x, val);
}
// FetchXorByteArrayOp_Int
-extern StgWord hs_atomic_xor8(StgWord x, StgWord val);
-StgWord
-hs_atomic_xor8(StgWord x, StgWord val)
+StgWord hs_atomic_xor8(StgWord x, StgWord val)
{
return __sync_fetch_and_xor((volatile StgWord8 *) x, (StgWord8) val);
}
-extern StgWord hs_atomic_xor16(StgWord x, StgWord val);
-StgWord
-hs_atomic_xor16(StgWord x, StgWord val)
+StgWord hs_atomic_xor16(StgWord x, StgWord val)
{
return __sync_fetch_and_xor((volatile StgWord16 *) x, (StgWord16) val);
}
-extern StgWord hs_atomic_xor32(StgWord x, StgWord val);
-StgWord
-hs_atomic_xor32(StgWord x, StgWord val)
+StgWord hs_atomic_xor32(StgWord x, StgWord val)
{
return __sync_fetch_and_xor((volatile StgWord32 *) x, (StgWord32) val);
}
-extern StgWord64 hs_atomic_xor64(StgWord x, StgWord64 val);
-StgWord64
-hs_atomic_xor64(StgWord x, StgWord64 val)
+StgWord64 hs_atomic_xor64(StgWord x, StgWord64 val)
{
return __sync_fetch_and_xor((volatile StgWord64 *) x, val);
}
// CasByteArrayOp_Int
-extern StgWord hs_cmpxchg8(StgWord x, StgWord old, StgWord new);
-StgWord
-hs_cmpxchg8(StgWord x, StgWord old, StgWord new)
+StgWord hs_cmpxchg8(StgWord x, StgWord old, StgWord new)
{
StgWord8 expected = (StgWord8) old;
__atomic_compare_exchange_n((StgWord8 *) x, &expected, (StgWord8) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
-extern StgWord hs_cmpxchg16(StgWord x, StgWord old, StgWord new);
-StgWord
-hs_cmpxchg16(StgWord x, StgWord old, StgWord new)
+StgWord hs_cmpxchg16(StgWord x, StgWord old, StgWord new)
{
StgWord16 expected = (StgWord16) old;
__atomic_compare_exchange_n((StgWord16 *) x, &expected, (StgWord16) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
-extern StgWord hs_cmpxchg32(StgWord x, StgWord old, StgWord new);
-StgWord
-hs_cmpxchg32(StgWord x, StgWord old, StgWord new)
+StgWord hs_cmpxchg32(StgWord x, StgWord old, StgWord new)
{
StgWord32 expected = (StgWord32) old;
__atomic_compare_exchange_n((StgWord32 *) x, &expected, (StgWord32) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
return expected;
}
-extern StgWord64 hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new);
-StgWord64
-hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new)
+StgWord64 hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new)
{
StgWord64 expected = (StgWord64) old;
__atomic_compare_exchange_n((StgWord64 *) x, &expected, (StgWord64) new, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST);
@@ -313,31 +257,23 @@ hs_cmpxchg64(StgWord x, StgWord64 old, StgWord64 new)
// Atomic exchange operations
-extern StgWord hs_xchg8(StgWord x, StgWord val);
-StgWord
-hs_xchg8(StgWord x, StgWord val)
+StgWord hs_xchg8(StgWord x, StgWord val)
{
return (StgWord) __atomic_exchange_n((StgWord8 *) x, (StgWord8) val, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_xchg16(StgWord x, StgWord val);
-StgWord
-hs_xchg16(StgWord x, StgWord val)
+StgWord hs_xchg16(StgWord x, StgWord val)
{
return (StgWord) __atomic_exchange_n((StgWord16 *)x, (StgWord16) val, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_xchg32(StgWord x, StgWord val);
-StgWord
-hs_xchg32(StgWord x, StgWord val)
+StgWord hs_xchg32(StgWord x, StgWord val)
{
return (StgWord) __atomic_exchange_n((StgWord32 *) x, (StgWord32) val, __ATOMIC_SEQ_CST);
}
//GCC provides this even on 32bit, but StgWord is still 32 bits.
-extern StgWord64 hs_xchg64(StgWord x, StgWord64 val);
-StgWord64
-hs_xchg64(StgWord x, StgWord64 val)
+StgWord64 hs_xchg64(StgWord x, StgWord64 val)
{
return (StgWord64) __atomic_exchange_n((StgWord64 *) x, (StgWord64) val, __ATOMIC_SEQ_CST);
}
@@ -352,30 +288,22 @@ hs_xchg64(StgWord x, StgWord64 val)
// primitives which the GCC documentation claims "usually" implies a full
// barrier.
-extern StgWord hs_atomicread8(StgWord x);
-StgWord
-hs_atomicread8(StgWord x)
+StgWord hs_atomicread8(StgWord x)
{
return __atomic_load_n((StgWord8 *) x, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_atomicread16(StgWord x);
-StgWord
-hs_atomicread16(StgWord x)
+StgWord hs_atomicread16(StgWord x)
{
return __atomic_load_n((StgWord16 *) x, __ATOMIC_SEQ_CST);
}
-extern StgWord hs_atomicread32(StgWord x);
-StgWord
-hs_atomicread32(StgWord x)
+StgWord hs_atomicread32(StgWord x)
{
return __atomic_load_n((StgWord32 *) x, __ATOMIC_SEQ_CST);
}
-extern StgWord64 hs_atomicread64(StgWord x);
-StgWord64
-hs_atomicread64(StgWord x)
+StgWord64 hs_atomicread64(StgWord x)
{
return __atomic_load_n((StgWord64 *) x, __ATOMIC_SEQ_CST);
}
@@ -384,30 +312,22 @@ hs_atomicread64(StgWord x)
// Implies a full memory barrier (see compiler/GHC/Builtin/primops.txt.pp)
// __ATOMIC_SEQ_CST: Full barrier (see hs_atomicread8 above).
-extern void hs_atomicwrite8(StgWord x, StgWord val);
-void
-hs_atomicwrite8(StgWord x, StgWord val)
+void hs_atomicwrite8(StgWord x, StgWord val)
{
__atomic_store_n((StgWord8 *) x, (StgWord8) val, __ATOMIC_SEQ_CST);
}
-extern void hs_atomicwrite16(StgWord x, StgWord val);
-void
-hs_atomicwrite16(StgWord x, StgWord val)
+void hs_atomicwrite16(StgWord x, StgWord val)
{
__atomic_store_n((StgWord16 *) x, (StgWord16) val, __ATOMIC_SEQ_CST);
}
-extern void hs_atomicwrite32(StgWord x, StgWord val);
-void
-hs_atomicwrite32(StgWord x, StgWord val)
+void hs_atomicwrite32(StgWord x, StgWord val)
{
__atomic_store_n((StgWord32 *) x, (StgWord32) val, __ATOMIC_SEQ_CST);
}
-extern void hs_atomicwrite64(StgWord x, StgWord64 val);
-void
-hs_atomicwrite64(StgWord x, StgWord64 val)
+void hs_atomicwrite64(StgWord x, StgWord64 val)
{
__atomic_store_n((StgWord64 *) x, (StgWord64) val, __ATOMIC_SEQ_CST);
}
=====================================
libraries/ghc-internal/cbits/bitrev.c → rts/prim/bitrev.c
=====================================
=====================================
libraries/ghc-internal/cbits/bswap.c → rts/prim/bswap.c
=====================================
=====================================
libraries/ghc-internal/cbits/clz.c → rts/prim/clz.c
=====================================
=====================================
libraries/ghc-internal/cbits/ctz.c → rts/prim/ctz.c
=====================================
=====================================
libraries/ghc-internal/cbits/int64x2minmax.c → rts/prim/int64x2minmax.c
=====================================
=====================================
libraries/ghc-internal/cbits/longlong.c → rts/prim/longlong.c
=====================================
=====================================
libraries/ghc-internal/cbits/mulIntMayOflo.c → rts/prim/mulIntMayOflo.c
=====================================
=====================================
libraries/ghc-internal/cbits/pdep.c → rts/prim/pdep.c
=====================================
=====================================
libraries/ghc-internal/cbits/pext.c → rts/prim/pext.c
=====================================
=====================================
libraries/ghc-internal/cbits/popcnt.c → rts/prim/popcnt.c
=====================================
=====================================
libraries/ghc-internal/cbits/vectorQuotRem.c → rts/prim/vectorQuotRem.c
=====================================
=====================================
libraries/ghc-internal/cbits/word2float.c → rts/prim/word2float.c
=====================================
=====================================
rts/rts.cabal
=====================================
@@ -529,6 +529,19 @@ library
sm/Storage.c
sm/Sweep.c
fs.c
+ prim/atomic.c
+ prim/bitrev.c
+ prim/bswap.c
+ prim/clz.c
+ prim/ctz.c
+ prim/int64x2minmax.c
+ prim/longlong.c
+ prim/mulIntMayOflo.c
+ prim/pdep.c
+ prim/pext.c
+ prim/popcnt.c
+ prim/vectorQuotRem.c
+ prim/word2float.c
-- I wish we had wildcards..., this would be:
-- *.c hooks/**/*.c sm/**/*.c eventlog/**/*.c linker/**/*.c
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1e62b9c9238220ece0fc567064931f8…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/1e62b9c9238220ece0fc567064931f8…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/andreask/occ_anal_tuning] OccAnal: Be stricter.
by Andreas Klebinger (@AndreasK) 10 Oct '25
by Andreas Klebinger (@AndreasK) 10 Oct '25
10 Oct '25
Andreas Klebinger pushed to branch wip/andreask/occ_anal_tuning at Glasgow Haskell Compiler / GHC
Commits:
3f2d549e by Andreas Klebinger at 2025-10-10T14:22:32+02:00
OccAnal: Be stricter.
* When combining usageDetails.
* When constructing core expressions.
In combineUsageDetails when combining the underlying adds we compute a
new `LocalOcc` for each entry by combining the two existing ones.
Rather than wait for those entries to be forced down the road we now
force them immediately. Speeding up T26425 by about 10% with little
effect on the common case.
We also force CoreExprs we construct in order to prevent them from
captuing the OccAnal Env massively reducing residency in some cases.
For T26425 residency went down by a factor of ~10x.
-------------------------
Metric Decrease:
T26425
-------------------------
- - - - -
4 changed files:
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Data/Graph/UnVar.hs
- compiler/GHC/Types/Unique/FM.hs
- compiler/GHC/Types/Var/Env.hs
Changes:
=====================================
compiler/GHC/Core/Opt/OccurAnal.hs
=====================================
@@ -9,6 +9,8 @@
-- many /other/ arguments the function has. Inconsistent unboxing is very
-- bad for performance, so I increased the limit to allow it to unbox
-- consistently.
+-- AK: Seems we no longer unbox OccEnv now anyway so it might be redundant.
+
{-
(c) The GRASP/AQUA Project, Glasgow University, 1992-1998
@@ -37,6 +39,7 @@ import GHC.Core.Utils ( exprIsTrivial, isDefaultAlt, isExpandableApp,
mkCastMCo, mkTicks )
import GHC.Core.Opt.Arity ( joinRhsArity, isOneShotBndr )
import GHC.Core.Coercion
+import GHC.Core.Seq (seqExpr)
import GHC.Core.Type
import GHC.Core.TyCo.FVs ( tyCoVarsOfMCo )
@@ -984,7 +987,7 @@ occAnalBind !env lvl ire (NonRec bndr rhs) thing_inside combine
= -- Analyse the RHS and /then/ the body
let -- Analyse the rhs first, generating rhs_uds
!(rhs_uds_s, bndr', rhs') = occAnalNonRecRhs env lvl ire mb_join bndr rhs
- rhs_uds = foldr1 orUDs rhs_uds_s -- NB: orUDs. See (W4) of
+ rhs_uds = foldl1' orUDs rhs_uds_s -- NB: orUDs. See (W4) of
-- Note [Occurrence analysis for join points]
-- Now analyse the body, adding the join point
@@ -1049,6 +1052,7 @@ occAnalNonRecRhs !env lvl imp_rule_edges mb_join bndr rhs
-- Match join arity O from mb_join_arity with manifest join arity M as
-- returned by of occAnalLamTail. It's totally OK for them to mismatch;
-- hence adjust the UDs from the RHS
+
WUD adj_rhs_uds final_rhs = adjustNonRecRhs mb_join $
occAnalLamTail rhs_env rhs
final_bndr_with_rules
@@ -2188,7 +2192,8 @@ occ_anal_lam_tail env expr@(Lam {})
go env rev_bndrs body
= addInScope env rev_bndrs $ \env ->
let !(WUD usage body') = occ_anal_lam_tail env body
- wrap_lam body bndr = Lam (tagLamBinder usage bndr) body
+ wrap_lam !body !bndr = let !bndr' = (tagLamBinder usage bndr)
+ in Lam bndr' body
in WUD (usage `addLamCoVarOccs` rev_bndrs)
(foldl' wrap_lam body' rev_bndrs)
@@ -2541,7 +2546,7 @@ occAnal env (Case scrut bndr ty alts)
let alt_env = addBndrSwap scrut' bndr $
setTailCtxt env -- Kill off OccRhs
WUD alts_usage alts' = do_alts alt_env alts
- tagged_bndr = tagLamBinder alts_usage bndr
+ !tagged_bndr = tagLamBinder alts_usage bndr
in WUD alts_usage (tagged_bndr, alts')
total_usage = markAllNonTail scrut_usage `andUDs` alts_usage
@@ -2561,11 +2566,16 @@ occAnal env (Case scrut bndr ty alts)
let WUD rhs_usage rhs' = occAnal env rhs
tagged_bndrs = tagLamBinders rhs_usage bndrs
in -- See Note [Binders in case alternatives]
- WUD rhs_usage (Alt con tagged_bndrs rhs')
+ seqList tagged_bndrs -- avoid retaining the occEnv
+ $ WUD rhs_usage (Alt con tagged_bndrs rhs')
occAnal env (Let bind body)
= occAnalBind env NotTopLevel noImpRuleEdges bind
- (\env -> occAnal env body) mkLets
+ (\env -> occAnal env body)
+ -- Without the seqs we construct a `Let` whos body is a
+ -- a thunk retaining the whole OccEnv until forced by the simplifier.
+ (\bndrs body -> (seqExpr body) `seq` (seqList bndrs) `seq` mkLets bndrs body)
+ -- mkLets
occAnalArgs :: OccEnv -> CoreExpr -> [CoreExpr]
-> [OneShots] -- Very commonly empty, notably prior to dmd anal
@@ -2644,10 +2654,12 @@ occAnalApp !env (Var fun, args, ticks)
| fun `hasKey` runRWKey
, [t1, t2, arg] <- args
, WUD usage arg' <- adjustNonRecRhs (JoinPoint 1) $ occAnalLamTail env arg
- = WUD usage (mkTicks ticks $ mkApps (Var fun) [t1, t2, arg'])
+ = let app_out = (mkTicks ticks $ mkApps (Var fun) [t1, t2, arg'])
+ in seq (seqExpr app_out) $ WUD usage app_out
occAnalApp env (Var fun_id, args, ticks)
- = WUD all_uds (mkTicks ticks app')
+ = let app_out = (mkTicks ticks app')
+ in seqExpr app_out `seq` WUD all_uds app_out
where
-- Lots of banged bindings: this is a very heavily bit of code,
-- so it pays not to make lots of thunks here, all of which
@@ -2692,8 +2704,9 @@ occAnalApp env (Var fun_id, args, ticks)
-- See Note [Sources of one-shot information], bullet point A']
occAnalApp env (fun, args, ticks)
- = WUD (markAllNonTail (fun_uds `andUDs` args_uds))
- (mkTicks ticks app')
+ = let app_out = (mkTicks ticks app')
+ in seqExpr app_out `seq` WUD (markAllNonTail (fun_uds `andUDs` args_uds)) app_out
+
where
!(WUD args_uds app') = occAnalArgs env fun' args []
!(WUD fun_uds fun') = occAnal (addAppCtxt env args) fun
@@ -3650,8 +3663,8 @@ data WithTailUsageDetails a = WTUD !TailUsageDetails !a
-------------------
-- UsageDetails API
-andUDs, orUDs
- :: UsageDetails -> UsageDetails -> UsageDetails
+andUDs:: UsageDetails -> UsageDetails -> UsageDetails
+orUDs :: UsageDetails -> UsageDetails -> UsageDetails
andUDs = combineUsageDetailsWith andLocalOcc
orUDs = combineUsageDetailsWith orLocalOcc
@@ -3759,17 +3772,18 @@ restrictFreeVars bndrs fvs = restrictUniqSetToUFM bndrs fvs
combineUsageDetailsWith :: (LocalOcc -> LocalOcc -> LocalOcc)
-> UsageDetails -> UsageDetails -> UsageDetails
-{-# INLINE combineUsageDetailsWith #-}
combineUsageDetailsWith plus_occ_info
uds1@(UD { ud_env = env1, ud_z_many = z_many1, ud_z_in_lam = z_in_lam1, ud_z_tail = z_tail1 })
uds2@(UD { ud_env = env2, ud_z_many = z_many2, ud_z_in_lam = z_in_lam2, ud_z_tail = z_tail2 })
| isEmptyVarEnv env1 = uds2
| isEmptyVarEnv env2 = uds1
| otherwise
- = UD { ud_env = plusVarEnv_C plus_occ_info env1 env2
- , ud_z_many = plusVarEnv z_many1 z_many2
- , ud_z_in_lam = plusVarEnv z_in_lam1 z_in_lam2
- , ud_z_tail = plusVarEnv z_tail1 z_tail2 }
+ -- Using strictPlusVarEnv here speeds up the test T26425 by about 10% by avoiding
+ -- intermediate thunks.
+ = UD { ud_env = strictPlusVarEnv_C plus_occ_info env1 env2
+ , ud_z_many = strictPlusVarEnv z_many1 z_many2
+ , ud_z_in_lam = strictPlusVarEnv z_in_lam1 z_in_lam2
+ , ud_z_tail = strictPlusVarEnv z_tail1 z_tail2 }
lookupLetOccInfo :: UsageDetails -> Id -> OccInfo
-- Don't use locally-generated occ_info for exported (visible-elsewhere)
=====================================
compiler/GHC/Data/Graph/UnVar.hs
=====================================
@@ -17,8 +17,8 @@ equal to g, but twice as expensive and large.
module GHC.Data.Graph.UnVar
( UnVarSet
, emptyUnVarSet, mkUnVarSet, unionUnVarSet, unionUnVarSets
- , extendUnVarSet, extendUnVarSetList, delUnVarSet, delUnVarSetList
- , elemUnVarSet, isEmptyUnVarSet
+ , extendUnVarSet, extendUnVarSet_Directly, extendUnVarSetList, delUnVarSet, delUnVarSetList
+ , elemUnVarSet, elemUnVarSet_Directly, isEmptyUnVarSet
, UnVarGraph
, emptyUnVarGraph
, unionUnVarGraph, unionUnVarGraphs
@@ -60,6 +60,9 @@ emptyUnVarSet = UnVarSet S.empty
elemUnVarSet :: Var -> UnVarSet -> Bool
elemUnVarSet v (UnVarSet s) = k v `S.member` s
+{-# INLINE elemUnVarSet_Directly #-}
+elemUnVarSet_Directly :: Uniquable key => key -> UnVarSet -> Bool
+elemUnVarSet_Directly v (UnVarSet s) = (getKey $ getUnique v) `S.member` s
isEmptyUnVarSet :: UnVarSet -> Bool
isEmptyUnVarSet (UnVarSet s) = S.null s
@@ -82,6 +85,10 @@ mkUnVarSet vs = UnVarSet $ S.fromList $ map k vs
extendUnVarSet :: Var -> UnVarSet -> UnVarSet
extendUnVarSet v (UnVarSet s) = UnVarSet $ S.insert (k v) s
+{-# INLINE extendUnVarSet_Directly #-}
+extendUnVarSet_Directly :: Uniquable key => key -> UnVarSet -> UnVarSet
+extendUnVarSet_Directly u (UnVarSet s) = UnVarSet $ S.insert (getKey $ getUnique u) s
+
extendUnVarSetList :: [Var] -> UnVarSet -> UnVarSet
extendUnVarSetList vs s = s `unionUnVarSet` mkUnVarSet vs
=====================================
compiler/GHC/Types/Unique/FM.hs
=====================================
@@ -51,7 +51,9 @@ module GHC.Types.Unique.FM (
delListFromUFM,
delListFromUFM_Directly,
plusUFM,
+ strictPlusUFM,
plusUFM_C,
+ strictPlusUFM_C,
plusUFM_CD,
plusUFM_CD2,
mergeUFM,
@@ -251,16 +253,24 @@ delListFromUFM_Directly = foldl' delFromUFM_Directly
delFromUFM_Directly :: UniqFM key elt -> Unique -> UniqFM key elt
delFromUFM_Directly (UFM m) u = UFM (M.delete (getKey u) m)
--- Bindings in right argument shadow those in the left
+-- | Bindings in right argument shadow those in the left.
+--
+-- Unlike containers this union is right-biased for historic reasons.
plusUFM :: UniqFM key elt -> UniqFM key elt -> UniqFM key elt
--- M.union is left-biased, plusUFM should be right-biased.
plusUFM (UFM x) (UFM y) = UFM (M.union y x)
-- Note (M.union y x), with arguments flipped
-- M.union is left-biased, plusUFM should be right-biased.
+-- | Right biased
+strictPlusUFM :: UniqFM key elt -> UniqFM key elt -> UniqFM key elt
+strictPlusUFM (UFM x) (UFM y) = UFM (MS.union y x)
+
plusUFM_C :: (elt -> elt -> elt) -> UniqFM key elt -> UniqFM key elt -> UniqFM key elt
plusUFM_C f (UFM x) (UFM y) = UFM (M.unionWith f x y)
+strictPlusUFM_C :: (elt -> elt -> elt) -> UniqFM key elt -> UniqFM key elt -> UniqFM key elt
+strictPlusUFM_C f (UFM x) (UFM y) = UFM (MS.unionWith f x y)
+
-- | `plusUFM_CD f m1 d1 m2 d2` merges the maps using `f` as the
-- combinding function and `d1` resp. `d2` as the default value if
-- there is no entry in `m1` reps. `m2`. The domain is the union of
=====================================
compiler/GHC/Types/Var/Env.hs
=====================================
@@ -12,7 +12,8 @@ module GHC.Types.Var.Env (
elemVarEnv, disjointVarEnv, anyVarEnv,
extendVarEnv, extendVarEnv_C, extendVarEnv_Acc,
extendVarEnvList,
- plusVarEnv, plusVarEnv_C, plusVarEnv_CD, plusMaybeVarEnv_C,
+ strictPlusVarEnv, plusVarEnv, plusVarEnv_C, strictPlusVarEnv_C,
+ plusVarEnv_CD, plusMaybeVarEnv_C,
plusVarEnvList, alterVarEnv,
delVarEnvList, delVarEnv,
minusVarEnv,
@@ -511,6 +512,7 @@ extendVarEnv :: VarEnv a -> Var -> a -> VarEnv a
extendVarEnv_C :: (a->a->a) -> VarEnv a -> Var -> a -> VarEnv a
extendVarEnv_Acc :: (a->b->b) -> (a->b) -> VarEnv b -> Var -> a -> VarEnv b
plusVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
+strictPlusVarEnv :: VarEnv a -> VarEnv a -> VarEnv a
plusVarEnvList :: [VarEnv a] -> VarEnv a
extendVarEnvList :: VarEnv a -> [(Var, a)] -> VarEnv a
varEnvDomain :: VarEnv elt -> UnVarSet
@@ -522,6 +524,7 @@ delVarEnvList :: Foldable f => VarEnv a -> f Var -> VarEnv a
delVarEnv :: VarEnv a -> Var -> VarEnv a
minusVarEnv :: VarEnv a -> VarEnv b -> VarEnv a
plusVarEnv_C :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
+strictPlusVarEnv_C :: (a -> a -> a) -> VarEnv a -> VarEnv a -> VarEnv a
plusVarEnv_CD :: (a -> a -> a) -> VarEnv a -> a -> VarEnv a -> a -> VarEnv a
plusMaybeVarEnv_C :: (a -> a -> Maybe a) -> VarEnv a -> VarEnv a -> VarEnv a
mapVarEnv :: (a -> b) -> VarEnv a -> VarEnv b
@@ -548,6 +551,7 @@ extendVarEnv_C = addToUFM_C
extendVarEnv_Acc = addToUFM_Acc
extendVarEnvList = addListToUFM
plusVarEnv_C = plusUFM_C
+strictPlusVarEnv_C = strictPlusUFM_C
plusVarEnv_CD = plusUFM_CD
plusMaybeVarEnv_C = plusMaybeUFM_C
delVarEnvList = delListFromUFM
@@ -556,6 +560,7 @@ delVarEnvList = delListFromUFM
delVarEnv = delFromUFM
minusVarEnv = minusUFM
plusVarEnv = plusUFM
+strictPlusVarEnv = strictPlusUFM
plusVarEnvList = plusUFMList
-- lookupVarEnv is very hot (in part due to being called by substTyVar),
-- if it's not inlined than the mere allocation of the Just constructor causes
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3f2d549ece632573d1e36ee2c9b9725…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/3f2d549ece632573d1e36ee2c9b9725…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/andreask/bomb_out] exprSize: Accumulate size as we go to allow early bomb out.
by Andreas Klebinger (@AndreasK) 10 Oct '25
by Andreas Klebinger (@AndreasK) 10 Oct '25
10 Oct '25
Andreas Klebinger pushed to branch wip/andreask/bomb_out at Glasgow Haskell Compiler / GHC
Commits:
bec02195 by Andreas Klebinger at 2025-10-10T14:02:24+02:00
exprSize: Accumulate size as we go to allow early bomb out.
When dealing with branches in the AST we now accumulate
expr size across branches, rather than computing both
branches before adding them up.
This way we can abort early when it's clear an expression
is too large to be useful.
This fixes an issue I observed in #26425 where we sometimes
spent a significant amount of time computing unfolding sizes
in deeply nested but branching rhss.
Speedup is on the order of ~1%-4% depending on the program we
are compiling.
- - - - -
1 changed file:
- compiler/GHC/Core/Unfold.hs
Changes:
=====================================
compiler/GHC/Core/Unfold.hs
=====================================
@@ -1,3 +1,5 @@
+{-# LANGUAGE DataKinds #-}
+
{-
(c) The University of Glasgow 2006
(c) The AQUA Project, Glasgow University, 1994-1998
@@ -554,56 +556,63 @@ uncondInlineJoin bndrs body
go_arg (Var f) = Just $! f `notElem` bndrs
go_arg _ = Nothing
-
sizeExpr :: UnfoldingOpts
-> Int -- Bomb out if it gets bigger than this
-> [Id] -- Arguments; we're interested in which of these
-- get case'd
-> CoreExpr
- -> ExprSize
+ -> ExprSize WithDiscount
-- Note [Computing the size of an expression]
-- Forcing bOMB_OUT_SIZE early prevents repeated
-- unboxing of the Int argument.
sizeExpr opts !bOMB_OUT_SIZE top_args expr
- = size_up expr
+ = size_up 0 expr
where
- size_up (Cast e _) = size_up e
- size_up (Tick _ e) = size_up e
- size_up (Type _) = sizeZero -- Types cost nothing
- size_up (Coercion _) = sizeZero
- size_up (Lit lit) = sizeN (litSize lit)
- size_up (Var f) | isZeroBitId f = sizeZero
- -- Make sure we get constructor discounts even
- -- on nullary constructors
- | otherwise = size_up_call f [] 0
-
- size_up (App fun arg)
- | isTyCoArg arg = size_up fun
- | otherwise = size_up arg `addSizeNSD`
- size_up_app fun [arg] (if isZeroBitExpr arg then 1 else 0)
-
- size_up (Lam b e)
- | isId b && not (isZeroBitId b) = lamScrutDiscount opts (size_up e `addSizeN` 10)
- | otherwise = size_up e
-
- size_up (Let (NonRec binder rhs) body)
- = size_up_rhs (binder, rhs) `addSizeNSD`
- size_up body `addSizeN`
- size_up_alloc binder
-
- size_up (Let (Rec pairs) body)
- = foldr (addSizeNSD . size_up_rhs)
- (size_up body `addSizeN` sum (map (size_up_alloc . fst) pairs))
- pairs
-
- size_up (Case e _ _ alts) = case nonEmpty alts of
- Nothing -> size_up e -- case e of {} never returns, so take size of scrutinee
+ -- (size_up s e) returns `s` plus the size of `e`
+ size_up :: Int -> CoreExpr -> ExprSize WithDiscount
+ size_up acc_size (Cast e _) = size_up acc_size e
+ size_up acc_size (Tick _ e) = size_up acc_size e
+ size_up acc_size (Type _) = mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0 -- Types cost nothing
+ size_up acc_size (Coercion _) = mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0
+ size_up acc_size (Lit lit) = (mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0) `addSizeND` litSize lit
+ size_up acc_size (Var f) | isZeroBitId f = mkSizeDiscount bOMB_OUT_SIZE acc_size emptyBag 0
+ -- Make sure we get constructor discounts even
+ -- on nullary constructors
+ | otherwise = size_up_call acc_size emptyBag f [] 0
+
+ size_up acc_size (App fun arg)
+ | isTyCoArg arg = size_up acc_size fun
+ | otherwise = case size_up acc_size arg of
+ TooBig -> TooBig
+ SizeIs acc_size' acc_args' _d -> size_up_app acc_size' acc_args'
+ fun [arg] (if isZeroBitExpr arg then 1 else 0)
+
+ size_up acc_size (Lam b e)
+ | isId b && not (isZeroBitId b) = lamScrutDiscount opts (size_up (acc_size+10) e)
+ | otherwise = size_up acc_size e
+
+ size_up acc_size (Let (NonRec binder rhs) body)
+ = case size_up_let acc_size emptyBag (binder, rhs) of
+ TooBig -> TooBig
+ SizeIs acc_size' acc_args' _d -> size_up acc_size' body `addSizeB` acc_args'
+
+ size_up acc_size (Let (Rec pairs) body)
+ = do_pairs acc_size emptyBag pairs
+ where
+ do_pairs acc_size acc_args [] = size_up acc_size body `addSizeB` acc_args
+ do_pairs acc_size acc_args (pair:pairs) =
+ case size_up_let acc_size acc_args pair of
+ TooBig -> TooBig
+ SizeIs acc_size' acc_args' _d -> do_pairs acc_size' acc_args' pairs
+
+ size_up acc_size (Case e _ _ alts) = case nonEmpty alts of
+ Nothing -> size_up acc_size e -- case e of {} never returns, so take size of scrutinee
Just alts
| Just v <- is_top_arg e -> -- We are scrutinising an argument variable
let
- alt_sizes = NE.map size_up_alt alts
+ alt_sizes = NE.map (size_up_alt acc_size) alts
-- alts_size tries to compute a good discount for
-- the case when we are scrutinising an argument variable
@@ -625,14 +634,15 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
alts_size tot_size _ = tot_size
in
- alts_size (foldr1 addAltSize alt_sizes) -- alts is non-empty
- (foldr1 maxSize alt_sizes)
+ mkSizeNoDiscount bOMB_OUT_SIZE acc_size emptyBag `addSizeNSD` alts_size (foldr1 addAltSize alt_sizes) -- alts is non-empty
+ (foldr1 maxSize alt_sizes)
-- Good to inline if an arg is scrutinised, because
-- that may eliminate allocation in the caller
-- And it eliminates the case itself
- | otherwise -> size_up e `addSizeNSD`
- foldr (addAltSize . size_up_alt) case_size alts
+ | otherwise -> foldr (addAltSize . (size_up_alt acc_size))
+ (size_up (acc_size + case_size) e)
+ alts
where
is_top_arg (Var v) | v `elem` top_args = Just v
@@ -641,9 +651,10 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
is_top_arg _ = Nothing
where
+ case_size :: Int
case_size
- | is_inline_scrut e, lengthAtMost alts 1 = sizeN (-10)
- | otherwise = sizeZero
+ | is_inline_scrut e, lengthAtMost alts 1 = (-10)
+ | otherwise = 0
-- Normally we don't charge for the case itself, but
-- we charge one per alternative (see size_up_alt,
-- below) to account for the cost of the info table
@@ -676,48 +687,64 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
| otherwise
= False
- size_up_rhs (bndr, rhs)
+ size_up_let :: Int -> Bag (Id,Int) -> (Id, CoreExpr) -> ExprSize NoDiscount
+ size_up_let acc_size acc_args (bndr, rhs)
| JoinPoint join_arity <- idJoinPointHood bndr
-- Skip arguments to join point
- , (_bndrs, body) <- collectNBinders join_arity rhs
- = size_up body
+ , (_bndrs, join_rhs) <- collectNBinders join_arity rhs
+ = (stripDiscounts $ size_up acc_size join_rhs) `addSizeB` acc_args
| otherwise
- = size_up rhs
+ = (stripDiscounts $ size_up (acc_size + size_up_alloc bndr) rhs) `addSizeB` acc_args
------------
-- size_up_app is used when there's ONE OR MORE value args
- size_up_app (App fun arg) args voids
- | isTyCoArg arg = size_up_app fun args voids
- | isZeroBitExpr arg = size_up_app fun (arg:args) (voids + 1)
- | otherwise = size_up arg `addSizeNSD`
- size_up_app fun (arg:args) voids
- size_up_app (Var fun) args voids = size_up_call fun args voids
- size_up_app (Tick _ expr) args voids = size_up_app expr args voids
- size_up_app (Cast expr _) args voids = size_up_app expr args voids
- size_up_app other args voids = size_up other `addSizeN`
- callSize (length args) voids
+ size_up_app :: Int -> Bag (Id,Int) -> CoreExpr -> [CoreExpr] -> Int -> ExprSize WithDiscount
+ size_up_app acc_size acc_args (App fun arg) args voids
+ | isTyCoArg arg = size_up_app acc_size acc_args fun args voids
+ | isZeroBitExpr arg = size_up_app acc_size acc_args fun (arg:args) (voids + 1)
+ | otherwise = case size_up acc_size arg of
+ TooBig -> TooBig
+ SizeIs acc_size' acc_args' _ ->
+ size_up_app acc_size' acc_args' fun (arg:args) voids
+ `addSizeB` acc_args
+ size_up_app acc_size acc_args (Var fun) args voids = size_up_call acc_size acc_args fun args voids
+ size_up_app acc_size acc_args (Tick _ expr) args voids = size_up_app acc_size acc_args expr args voids
+ size_up_app acc_size acc_args (Cast expr _) args voids = size_up_app acc_size acc_args expr args voids
+ size_up_app acc_size acc_args other args voids = size_up (acc_size + callSize (length args) voids) other `addSizeB` acc_args
+
-- if the lhs is not an App or a Var, or an invisible thing like a
-- Tick or Cast, then we should charge for a complete call plus the
-- size of the lhs itself.
------------
- size_up_call :: Id -> [CoreExpr] -> Int -> ExprSize
- size_up_call fun val_args voids
- = case idDetails fun of
- FCallId _ -> sizeN (callSize (length val_args) voids)
- DataConWorkId dc -> conSize dc (length val_args)
- PrimOpId op _ -> primOpSize op (length val_args)
- ClassOpId cls _ -> classOpSize opts cls top_args val_args
- _ | fun `hasKey` buildIdKey -> buildSize
- | fun `hasKey` augmentIdKey -> augmentSize
- | otherwise -> funSize opts top_args fun (length val_args) voids
+ size_up_call :: Int -> Bag (Id,Int) -> Id -> [CoreExpr] -> Int -> ExprSize WithDiscount
+ size_up_call acc_size acc_args fun val_args voids
+ = let !n_args = length val_args
+ call_size = case idDetails fun of
+ FCallId _ -> withDiscount $ sizeN (callSize n_args voids)
+ DataConWorkId dc -> conSize dc n_args
+ PrimOpId op _ -> withDiscount $ primOpSize op n_args
+ ClassOpId cls _ -> withDiscount $ classOpSize opts cls top_args val_args
+ _ | fun `hasKey` buildIdKey -> buildSize
+ | fun `hasKey` augmentIdKey -> augmentSize
+ | otherwise -> funSize opts top_args fun n_args voids
+ in mkSizeNoDiscount bOMB_OUT_SIZE acc_size acc_args `addSizeNSD` call_size
------------
- size_up_alt (Alt _con _bndrs rhs) = size_up rhs `addSizeN` 10
+ -- size_up_alt returns only the alternatives size, not counting the accumulated
+ -- size passed in unless we reach TooBig. This is to facility better discount
+ -- calculation based on the size of only the alternative.
+ -- size_up_alt acc_size acc_args = TooBig
+ size_up_alt acc_size (Alt _con _bndrs rhs) =
+ size_up acc_size rhs
+ -- Why add and then subtract s?
+ -- If the expression large enough this will ensure we bomb out early.
+ `addSizeND` (10 -acc_size)
+
-- Don't charge for args, so that wrappers look cheap
-- (See comments about wrappers with Case)
--
- -- IMPORTANT: *do* charge 1 for the alternative, else we
+ -- IMPORTANT: *do* charge 10 for the alternative, else we
-- find that giant case nests are treated as practically free
-- A good example is Foreign.C.Error.errnoToIOError
@@ -734,26 +761,40 @@ sizeExpr opts !bOMB_OUT_SIZE top_args expr
------------
-- These addSize things have to be here because
-- I don't want to give them bOMB_OUT_SIZE as an argument
- addSizeN TooBig _ = TooBig
- addSizeN (SizeIs n xs d) m = mkSizeIs bOMB_OUT_SIZE (n + m) xs d
+ addSizeND :: ExprSize WithDiscount -> Int -> ExprSize WithDiscount
+ addSizeND TooBig _ = TooBig
+ addSizeND (SizeIs n xs d) m = mkSizeDiscount bOMB_OUT_SIZE (n + m) xs d
+ addSizeB :: ExprSize a -> Bag (Id,Int) -> ExprSize a
+ addSizeB TooBig _ = TooBig
+ addSizeB (SizeIs sz bg1 dc) bg2 = SizeIs sz (bg1 `unionBags` bg2) dc
-- addAltSize is used to add the sizes of case alternatives
addAltSize TooBig _ = TooBig
addAltSize _ TooBig = TooBig
addAltSize (SizeIs n1 xs d1) (SizeIs n2 ys d2)
- = mkSizeIs bOMB_OUT_SIZE (n1 + n2)
+ = mkSizeDiscount bOMB_OUT_SIZE (n1 + n2)
(xs `unionBags` ys)
(d1 + d2) -- Note [addAltSize result discounts]
-- This variant ignores the result discount from its LEFT argument
-- It's used when the second argument isn't part of the result
+ addSizeNSD :: ExprSize NoDiscount -> ExprSize WithDiscount -> ExprSize WithDiscount
addSizeNSD TooBig _ = TooBig
addSizeNSD _ TooBig = TooBig
addSizeNSD (SizeIs n1 xs _) (SizeIs n2 ys d2)
- = mkSizeIs bOMB_OUT_SIZE (n1 + n2)
+ = mkSizeDiscount bOMB_OUT_SIZE (n1 + n2)
(xs `unionBags` ys)
d2 -- Ignore d1
+ -- Throw away the discount for scrutinizing the expression.
+ -- Used for things like `let x = rhs in body` where we only consider
+ -- this benefit for the body.
+ -- Why? `x` is visible to `body` either way, so it really should not
+ -- affect our inlining decision either way.
+ stripDiscounts :: ExprSize a -> ExprSize NoDiscount
+ stripDiscounts TooBig = TooBig
+ stripDiscounts (SizeIs n xs _) = (SizeIs n xs 0)
+
-- don't count expressions such as State# RealWorld
-- exclude join points, because they can be rep-polymorphic
-- and typePrimRep will crash
@@ -775,7 +816,7 @@ litSize _other = 0 -- Must match size of nullary constructors
-- Key point: if x |-> 4, then x must inline unconditionally
-- (eg via case binding)
-classOpSize :: UnfoldingOpts -> Class -> [Id] -> [CoreExpr] -> ExprSize
+classOpSize :: UnfoldingOpts -> Class -> [Id] -> [CoreExpr] -> ExprSize NoDiscount
-- See Note [Conlike is interesting]
classOpSize opts cls top_args args
| isUnaryClass cls
@@ -818,7 +859,7 @@ jumpSize _n_val_args _voids = 0 -- Jumps are small, and we don't want penalise
-- spectral/puzzle. TODO Perhaps adjusting the default threshold would be a
-- better solution?
-funSize :: UnfoldingOpts -> [Id] -> Id -> Int -> Int -> ExprSize
+funSize :: UnfoldingOpts -> [Id] -> Id -> Int -> Int -> ExprSize WithDiscount
-- Size for function calls where the function is not a constructor or primops
-- Note [Function applications]
funSize opts top_args fun n_val_args voids
@@ -844,14 +885,14 @@ funSize opts top_args fun n_val_args voids
-- If the function is partially applied, show a result discount
-- XXX maybe behave like ConSize for eval'd variable
-conSize :: DataCon -> Int -> ExprSize
+conSize :: DataCon -> Int -> ExprSize WithDiscount
conSize dc n_val_args
| n_val_args == 0 = SizeIs 0 emptyBag 10 -- Like variables
-- See Note [Unboxed tuple size and result discount]
| isUnboxedTupleDataCon dc = SizeIs 0 emptyBag 10
- | isUnaryClassDataCon dc = sizeZero
+ | isUnaryClassDataCon dc = withDiscount sizeZero
-- See Note [Constructor size and result discount]
| otherwise = SizeIs 10 emptyBag 10
@@ -948,7 +989,7 @@ that mention a literal Integer, because the float-out pass will float
all those constants to top level.
-}
-primOpSize :: PrimOp -> Int -> ExprSize
+primOpSize :: PrimOp -> Int -> ExprSize NoDiscount
primOpSize op n_val_args
= if primOpOutOfLine op
then sizeN (op_size + n_val_args)
@@ -957,7 +998,7 @@ primOpSize op n_val_args
op_size = primOpCodeSize op
-buildSize :: ExprSize
+buildSize :: ExprSize WithDiscount
buildSize = SizeIs 0 emptyBag 40
-- We really want to inline applications of build
-- build t (\cn -> e) should cost only the cost of e (because build will be inlined later)
@@ -966,13 +1007,13 @@ buildSize = SizeIs 0 emptyBag 40
-- build is saturated (it usually is). The "-2" discounts for the \c n,
-- The "4" is rather arbitrary.
-augmentSize :: ExprSize
+augmentSize :: ExprSize WithDiscount
augmentSize = SizeIs 0 emptyBag 40
-- Ditto (augment t (\cn -> e) ys) should cost only the cost of
-- e plus ys. The -2 accounts for the \cn
-- When we return a lambda, give a discount if it's used (applied)
-lamScrutDiscount :: UnfoldingOpts -> ExprSize -> ExprSize
+lamScrutDiscount :: UnfoldingOpts -> ExprSize a -> ExprSize WithDiscount
lamScrutDiscount opts (SizeIs n vs _) = SizeIs n vs (unfoldingFunAppDiscount opts)
lamScrutDiscount _ TooBig = TooBig
@@ -1045,18 +1086,25 @@ In a function application (f a b)
Code for manipulating sizes
-}
+-- | Does an ExprSize include an evaluation Discount?
+data HasDiscount = NoDiscount | WithDiscount deriving (Eq)
+
-- | The size of a candidate expression for unfolding
-data ExprSize
+--
+-- We don't use a separate constructor without a discount field as the
+-- re-allocation here as the resulting re-allocation when converting
+-- between them outweights any benefit.
+data ExprSize (hasDiscount :: HasDiscount)
= TooBig
| SizeIs { _es_size_is :: {-# UNPACK #-} !Int -- ^ Size found
, _es_args :: !(Bag (Id,Int))
-- ^ Arguments cased herein, and discount for each such
, _es_discount :: {-# UNPACK #-} !Int
-- ^ Size to subtract if result is scrutinised by a case
- -- expression
+ -- expression. Must be zero if `hasDiscount == NoDiscount`
}
-instance Outputable ExprSize where
+instance Outputable (ExprSize a) where
ppr TooBig = text "TooBig"
ppr (SizeIs a _ c) = brackets (int a <+> int c)
@@ -1065,18 +1113,26 @@ instance Outputable ExprSize where
-- tup = (a_1, ..., a_99)
-- x = case tup of ...
--
-mkSizeIs :: Int -> Int -> Bag (Id, Int) -> Int -> ExprSize
-mkSizeIs max n xs d | (n - d) > max = TooBig
- | otherwise = SizeIs n xs d
+mkSizeDiscount :: Int -> Int -> Bag (Id, Int) -> Int -> ExprSize WithDiscount
+mkSizeDiscount max n xs d | (n - d) > max = TooBig
+ | otherwise = SizeIs n xs d
+
+mkSizeNoDiscount :: Int -> Int -> Bag (Id, Int) -> ExprSize NoDiscount
+mkSizeNoDiscount max n xs | n > max = TooBig
+ | otherwise = SizeIs n xs 0
-maxSize :: ExprSize -> ExprSize -> ExprSize
+maxSize :: ExprSize a -> ExprSize a -> ExprSize a
maxSize TooBig _ = TooBig
maxSize _ TooBig = TooBig
maxSize s1@(SizeIs n1 _ _) s2@(SizeIs n2 _ _) | n1 > n2 = s1
| otherwise = s2
+withDiscount :: ExprSize NoDiscount -> ExprSize WithDiscount
+withDiscount s = case s of
+ TooBig -> TooBig
+ SizeIs x1 x2 x3 -> SizeIs x1 x2 x3
-sizeZero :: ExprSize
-sizeN :: Int -> ExprSize
+sizeZero :: ExprSize NoDiscount
+sizeN :: Int -> ExprSize NoDiscount
sizeZero = SizeIs 0 emptyBag 0
sizeN n = SizeIs n emptyBag 0
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bec021954e6bdae85e20fcb9dc24da9…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/bec021954e6bdae85e20fcb9dc24da9…
You're receiving this email because of your account on gitlab.haskell.org.
1
0