16 Jan '26
Cheng Shao pushed new branch wip/perf-notes-less-pushes at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/perf-notes-less-pushes
You're receiving this email because of your account on gitlab.haskell.org.
1
0
16 Jan '26
Cheng Shao pushed new branch wip/libffi-clib-use-mirror at Glasgow Haskell Compiler / GHC
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/tree/wip/libffi-clib-use-mirror
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] base: remove GHC.JS.Prim.Internal.Build (#23432)
by Marge Bot (@marge-bot) 16 Jan '26
by Marge Bot (@marge-bot) 16 Jan '26
16 Jan '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
c343ef64 by Sylvain Henry at 2026-01-16T06:45:51-05:00
base: remove GHC.JS.Prim.Internal.Build (#23432)
See accepted CLC proposal https://github.com/haskell/core-libraries-committee/issues/329
- - - - -
4 changed files:
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- − libraries/base/src/GHC/JS/Prim/Internal/Build.hs
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c343ef64ceb67d77619547b2e77cc8c…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/c343ef64ceb67d77619547b2e77cc8c…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] compiler: fix regression when compiling foreign stubs in the rts unit
by Marge Bot (@marge-bot) 16 Jan '26
by Marge Bot (@marge-bot) 16 Jan '26
16 Jan '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
7b616b9f by Cheng Shao at 2026-01-16T06:45:00-05:00
compiler: fix regression when compiling foreign stubs in the rts unit
This patch fixes a regression when compiling foreign stubs in the rts
unit introduced in 05e25647f72bc102061af3f20478aa72bff6ff6e. A simple
revert would fix it, but it's better to implement a proper fix with
comment for better understanding of the underlying problem, see the
added comment for explanation.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
1 changed file:
- compiler/GHC/Driver/CodeOutput.hs
Changes:
=====================================
compiler/GHC/Driver/CodeOutput.hs
=====================================
@@ -296,10 +296,15 @@ outputForeignStubs logger tmpfs dflags unit_state mod location stubs
mk_include i = "#include \"" ++ ST.unpack i ++ "\"\n"
in case mrts_pkg of
Just rts_pkg -> concatMap mk_include (unitIncludes rts_pkg)
- -- This case only happens when compiling foreign stub for the rts
- -- library itself. The only time we do this at the moment is for
- -- IPE information for the RTS info tables
- Nothing -> ""
+ -- The Nothing case only happens when compiling
+ -- foreign stubs for the rts library itself (e.g.
+ -- building with +ipe), and the rts unit is not
+ -- registered yet.
+ --
+ -- The generated stubs may still use RTS API, so
+ -- we must ensure that Rts.h is included,
+ -- otherwise we may run into regressions (#26779).
+ Nothing -> "#include \"Rts.h\"\n"
-- wrapper code mentions the ffi_arg type, which comes from ffi.h
ffi_includes
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7b616b9f0236f4160f28923784b448f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/7b616b9f0236f4160f28923784b448f…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][master] 2 commits: Add evals for strict data-con args in worker-functions
by Marge Bot (@marge-bot) 16 Jan '26
by Marge Bot (@marge-bot) 16 Jan '26
16 Jan '26
Marge Bot pushed to branch master at Glasgow Haskell Compiler / GHC
Commits:
c56567ec by Simon Peyton Jones at 2026-01-15T23:19:04+00:00
Add evals for strict data-con args in worker-functions
This fixes #26722, by adding an eval in a worker for
arguments of strict data constructors, even if the
function body uses them strictly.
See (WIS1) in Note [Which Ids should be strictified]
I took the opportunity to make substantial improvements in the
documentation for call-by-value functions. See especially
Note [CBV Function Ids: overview] in GHC.Types.Id.Info
Note [Which Ids should be CBV candidates?] ditto
Note [EPT enforcement] in GHC.Stg.EnforceEpt
among others.
- - - - -
9719ce5d by Simon Peyton Jones at 2026-01-15T23:19:04+00:00
Improve `interestingArg`
This function analyses a function's argument to see if it is
interesting enough to deserve an inlining discount. Improvements
for
* LitRubbish arguments
* exprIsExpandable arguments
See Note [Interesting arguments] which is substantially rewritten.
- - - - -
20 changed files:
- compiler/GHC/Core/Opt/Arity.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Opt/WorkWrap/Utils.hs
- compiler/GHC/Core/Tidy.hs
- compiler/GHC/Core/Unfold.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/CoreToStg/Prep.hs
- compiler/GHC/Stg/EnforceEpt.hs
- compiler/GHC/Stg/Lint.hs
- compiler/GHC/StgToCmm/Closure.hs
- compiler/GHC/StgToCmm/Expr.hs
- compiler/GHC/Types/Id.hs
- compiler/GHC/Types/Id/Info.hs
- compiler/GHC/Types/Id/Make.hs
- testsuite/tests/simplCore/should_compile/T18013.stderr
- + testsuite/tests/simplCore/should_compile/T26722.hs
- + testsuite/tests/simplCore/should_compile/T26722.stderr
- testsuite/tests/simplCore/should_compile/all.T
Changes:
=====================================
compiler/GHC/Core/Opt/Arity.hs
=====================================
@@ -2515,7 +2515,7 @@ eta-reduce that are specific to Core and GHC:
See Note [Eta expanding primops].
(W) We may not undersaturate StrictWorkerIds.
- See Note [CBV Function Ids] in GHC.Types.Id.Info.
+ See Note [CBV Function Ids: overview] in GHC.Types.Id.Info.
Here is a list of historic accidents surrounding unsound eta-reduction:
@@ -2848,7 +2848,7 @@ cantEtaReduceFun fun
|| (isJust (idCbvMarks_maybe fun)) -- (W)
-- Don't undersaturate StrictWorkerIds.
- -- See Note [CBV Function Ids] in GHC.Types.Id.Info.
+ -- See Note [CBV Function Ids: overview] in GHC.Types.Id.Info.
{- *********************************************************************
=====================================
compiler/GHC/Core/Opt/Simplify/Utils.hs
=====================================
@@ -982,15 +982,58 @@ But we don't regard (f x y) as interesting, unless f is unsaturated.
If it's saturated and f hasn't inlined, then it's probably not going
to now!
-Note [Conlike is interesting]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-Consider
- f d = ...((*) d x y)...
- ... f (df d')...
-where df is con-like. Then we'd really like to inline 'f' so that the
-rule for (*) (df d) can fire. To do this
- a) we give a discount for being an argument of a class-op (eg (*) d)
- b) we say that a con-like argument (eg (df d)) is interesting
+Wrinkles:
+
+(IA1) Conlike is interesting.
+ Consider
+ f d = ...((*) d x y)...
+ ... f (df d')...
+ where df is con-like. Then we'd really like to inline 'f' so that the
+ rule for (*) (df d) can fire. To do this
+ a) we give a discount for being an argument of a class-op (eg (*) d)
+ b) we say that a con-like argument (eg (df d)) is interesting
+
+(IA2) OtherCon.
+ interestingArg returns
+ (a) NonTrivArg for an arg with an OtherCon [] unfolding
+ (b) ValueArg for an arg with an OtherCon [c1,c2..] unfolding.
+
+ Reason for (a): I found (in the GHC.Internal.Bignum.Integer module) that I was
+ inlining a pretty big function when all we knew was that its arguments
+ were evaluated, nothing more. That in turn make the enclosing function
+ too big to inline elsewhere.
+
+ Reason for (b): we want to inline integerCompare here
+ integerLt# :: Integer -> Integer -> Bool#
+ integerLt# (IS x) (IS y) = x <# y
+ integerLt# x y | LT <- integerCompare x y = 1#
+ integerLt# _ _ = 0#
+
+(IA3) Rubbish literals.
+ In a worker we might see
+ $wfoo x = let y = RUBBISH in
+ ...(g y True)...
+ where `g` has a wrapper that discards its first argment. We really really
+ want to inline g's wrapper, to expose that it discards its RUBBISH arg.
+ That may not happen if RUBBISH looks like TrivArg, so we use NonTrivArg
+ instead. See #26722. (This reverses the plan in #20035, but the problem
+ reported there appears to have gone away.)
+
+(IA4) Consider a call `f (g x)`. If `f` has a an argument discount on its argument,
+ then f's body scrutinises its argument in a `case` expression, or perhaps applies
+ it. We give the arg `(g x)` an ArgSummary of `NonTrivArg` so that `f` has a bit
+ of encouragment to inline in these cases.
+
+ Now consider `let y = g x in f y`. Now we have to look through y's unfolding.
+ When should we do so? Suppose we did inline `f` so we ended up with
+ let y = g x in ...(case y of alts)...
+ Then we'll call `exprIsConApp_maybe` on `y`; and that looks through "expandable"
+ unfoldings; indeed that's the whole purpose of `exprIsExpanadable`. See
+ Note [exprIsExpandable] in GHC.Core.Utils.
+
+ Conclusion: `interestingArg` should give some encouragement (NonTrivArg) to `f`
+ when the argument is expandable. Hence `uf_expandable` in the `Var` case.
+
-}
interestingArg :: SimplEnv -> CoreExpr -> ArgSummary
@@ -1005,7 +1048,7 @@ interestingArg env e = go env 0 e
ContEx tvs cvs ids e -> go (setSubstEnv env tvs cvs ids) n e
go _ _ (Lit l)
- | isLitRubbish l = TrivArg -- Leads to unproductive inlining in WWRec, #20035
+ | isLitRubbish l = NonTrivArg -- See (IA3) in Note [Interesting arguments]
| otherwise = ValueArg
go _ _ (Type _) = TrivArg
go _ _ (Coercion _) = TrivArg
@@ -1027,45 +1070,29 @@ interestingArg env e = go env 0 e
go_var n v
| isConLikeId v = ValueArg -- Experimenting with 'conlike' rather that
-- data constructors here
- -- DFuns are con-like; see Note [Conlike is interesting]
+ -- DFuns are con-like;
+ -- see (IA1) in Note [Interesting arguments]
| idArity v > n = ValueArg -- Catches (eg) primops with arity but no unfolding
| n > 0 = NonTrivArg -- Saturated or unknown call
| otherwise -- n==0, no value arguments; look for an interesting unfolding
= case idUnfolding v of
OtherCon [] -> NonTrivArg -- It's evaluated, but that's all we know
OtherCon _ -> ValueArg -- Evaluated and we know it isn't these constructors
- -- See Note [OtherCon and interestingArg]
+ -- See (IA2) in Note [Interesting arguments]
DFunUnfolding {} -> ValueArg -- We konw that idArity=0
CoreUnfolding{ uf_cache = cache }
| uf_is_conlike cache -> ValueArg -- Includes constructor applications
- | uf_is_value cache -> NonTrivArg -- Things like partial applications
+ | uf_expandable cache -> NonTrivArg -- See (IA4)
| otherwise -> TrivArg
BootUnfolding -> TrivArg
NoUnfolding -> TrivArg
-{- Note [OtherCon and interestingArg]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-interstingArg returns
- (a) NonTrivArg for an arg with an OtherCon [] unfolding
- (b) ValueArg for an arg with an OtherCon [c1,c2..] unfolding.
-
-Reason for (a): I found (in the GHC.Internal.Bignum.Integer module) that I was
-inlining a pretty big function when all we knew was that its arguments
-were evaluated, nothing more. That in turn make the enclosing function
-too big to inline elsewhere.
-
-Reason for (b): we want to inline integerCompare here
- integerLt# :: Integer -> Integer -> Bool#
- integerLt# (IS x) (IS y) = x <# y
- integerLt# x y | LT <- integerCompare x y = 1#
- integerLt# _ _ = 0#
-************************************************************************
+{- *********************************************************************
* *
SimplMode
* *
-************************************************************************
--}
+********************************************************************* -}
updModeForStableUnfoldings :: ActivationGhc -> SimplMode -> SimplMode
-- See Note [The environments of the Simplify pass]
=====================================
compiler/GHC/Core/Opt/SpecConstr.hs
=====================================
@@ -1994,7 +1994,7 @@ spec_one env fn arg_bndrs body (call_pat, rule_number)
spec_arity = count isId spec_lam_args
spec_join_arity | isJoinId fn = JoinPoint (length spec_call_args)
| otherwise = NotJoinPoint
- spec_id = asWorkerLikeId $
+ spec_id = setCbvCandidate $
mkLocalId spec_name ManyTy spec_id_ty
-- See Note [Transfer strictness]
`setIdDmdSig` spec_sig
@@ -2065,7 +2065,7 @@ mkSeqs seqees res_ty rhs =
addEval :: Var -> CoreExpr -> CoreExpr
addEval arg_id rhs
-- Argument representing strict field and it's worth passing via cbv
- | shouldStrictifyIdForCbv arg_id
+ | wantCbvForId arg_id
= Case (Var arg_id)
(localiseId arg_id) -- See (SCF1) in Note [SpecConstr and strict fields]
res_ty
=====================================
compiler/GHC/Core/Opt/WorkWrap.hs
=====================================
@@ -848,7 +848,7 @@ mkWWBindPair ww_opts fn_id fn_info fn_args fn_body work_uniq div
-- worker is join point iff wrapper is join point
-- (see Note [Don't w/w join points for CPR])
- work_id = asWorkerLikeId $
+ work_id = setCbvCandidate $
mkWorkerId work_uniq fn_id (exprType work_rhs)
`setIdOccInfo` occInfo fn_info
-- Copy over occurrence info from parent
=====================================
compiler/GHC/Core/Opt/WorkWrap/Utils.hs
=====================================
@@ -914,23 +914,26 @@ C) Unlift *any* (non-boot exported) functions arguments if they are strict.
an impedance matcher function. Leading to massive code bloat.
Essentially we end up creating a impromptu wrapper function
wherever we wouldn't inline the wrapper with a W/W approach.
- ~ There is the option of achieving this without eta-expansion if we instead expand
- the partial application code to check for demands on the calling convention and
- for it to evaluate the arguments. The main downsides there would be the complexity
- of the implementation and that it carries a certain overhead even for functions who
- don't take advantage of this functionality. I haven't tried this approach because it's
- not trivial to implement and doing W/W splits seems to work well enough.
-
-Currently we use the first approach A) by default, with a flag that allows users to fall back to the
-more aggressive approach B).
-
-I also tried the third approach C) using eta-expansion at call sites to avoid modifying the PAP-handling
-code which wasn't fruitful. See https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5614#note_389903.
-We could still try to do C) in the future by having PAP calls which will evaluate the required arguments
-before calling the partially applied function. But this would be neither a small nor simple change so we
-stick with A) and a flag for B) for now.
-
-See also Note [EPT enforcement] and Note [CBV Function Ids]
+ ~ There is the option of achieving this without eta-expansion if we instead
+ expand the partial application code to check for demands on the calling
+ convention and for it to evaluate the arguments. The main downsides there
+ would be the complexity of the implementation and that it carries a
+ certain overhead even for functions who don't take advantage of this
+ functionality. I haven't tried this approach because it's not trivial to
+ implement and doing W/W splits seems to work well enough.
+
+Currently we use the first approach A) by default, with a flag that allows users
+to fall back to the more aggressive approach B).
+
+I also tried the third approach C) using eta-expansion at call sites to avoid
+modifying the PAP-handling code which wasn't fruitful. See
+https://gitlab.haskell.org/ghc/ghc/-/merge_requests/5614#note_389903. We could
+still try to do C) in the future by having PAP calls which will evaluate the
+required arguments before calling the partially applied function. But this would
+be neither a small nor simple change so we stick with A) and a flag for B) for
+now.
+
+See also Note [EPT enforcement] and Note [CBV Function Ids: overview]
Note [Worker/wrapper for strict arguments]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -954,7 +957,7 @@ an "eval" (see `GHC.StgToCmm.Expr.cgCase`). A call (f (a:as)) will
have the wrapper inlined, and will drop the `case x`, so no eval
happens at all.
-The worker `$wf` is a CBV function (see `Note [CBV Function Ids]`
+The worker `$wf` is a CBV function (see `Note [CBV Function Ids: overview]`
in GHC.Types.Id.Info) and the code generator guarantees that every
call to `$wf` has a properly tagged argument (see `GHC.Stg.EnforceEpt.Rewrite`).
@@ -1044,7 +1047,7 @@ mkWWstr_one opts arg str_mark =
DontUnbox
| isStrictDmd arg_dmd || isMarkedStrict str_mark
- , wwUseForUnlifting opts -- See Note [CBV Function Ids]
+ , wwUseForUnlifting opts -- See Note [WW for calling convention]
, not (isFunTy arg_ty)
, not (isUnliftedType arg_ty) -- Already unlifted!
-- NB: function arguments have a fixed RuntimeRep,
@@ -1311,12 +1314,13 @@ Needless to say, there are some wrinkles:
But that also means we emit a rubbish lit for other args that have
cardinality 'C_10' (say, the arg to a bottoming function) where we could've
used an error-thunk.
- NB from Andreas: But I think using an error thunk there would be dodgy no matter what
- for example if we decide to pass the argument to the bottoming function cbv.
- As we might do if the function in question is a worker.
- See Note [CBV Function Ids] in GHC.Types.Id.Info. So I just left the strictness check
- in place on top of threading through the marks from the constructor. It's a *really* cheap
- and easy check to make anyway.
+
+ NB from Andreas: But I think using an error thunk there would be dodgy no
+ matter what for example if we decide to pass the argument to the bottoming
+ function cbv. As we might do if the function in question is a worker. See
+ Note [CBV Function Ids: overview] in GHC.Types.Id.Info. So I just left the
+ strictness check in place on top of threading through the marks from the
+ constructor. It's a *really* cheap and easy check to make anyway.
(AF3) We can only emit a LitRubbish if the arg's type `arg_ty` is mono-rep, e.g.
of the form `TYPE rep` where `rep` is not (and doesn't contain) a variable.
=====================================
compiler/GHC/Core/Tidy.hs
=====================================
@@ -38,7 +38,7 @@ import GHC.Utils.Outputable
import GHC.Types.RepType (typePrimRep)
import GHC.Utils.Panic
import GHC.Types.Basic (isMarkedCbv, CbvMark (..))
-import GHC.Core.Utils (shouldUseCbvForId)
+import GHC.Core.Utils ( wantCbvForId )
{-
************************************************************************
@@ -70,52 +70,52 @@ tidyBind env (Rec prs)
(env', Rec (zip bndrs' rhss'))
--- Note [Attaching CBV Marks to ids]
--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
--- See Note [CBV Function Ids] for the *why*.
--- Before tidy, we turn all worker functions into worker like ids.
--- This way we can later tell if we can assume the existence of a wrapper. This also applies to
--- specialized versions of functions generated by SpecConstr for which we, in a sense,
--- consider the unspecialized version to be the wrapper.
--- During tidy we take the demands on the arguments for these ids and compute
--- CBV (call-by-value) semantics for each individual argument.
--- The marks themselves then are put onto the function id itself.
--- This means the code generator can get the full calling convention by only looking at the function
--- itself without having to inspect the RHS.
---
--- The actual logic is in computeCbvInfo and takes:
--- * The function id
--- * The functions rhs
--- And gives us back the function annotated with the marks.
--- We call it in:
--- * tidyTopPair for top level bindings
--- * tidyBind for local bindings.
---
--- Not that we *have* to look at the untidied rhs.
--- During tidying some knot-tying occurs which can blow up
--- if we look at the post-tidy types of the arguments here.
--- However we only care if the types are unlifted and that doesn't change during tidy.
--- so we can just look at the untidied types.
---
--- If the id is boot-exported we don't use a cbv calling convention via marks,
--- as the boot file won't contain them. Which means code calling boot-exported
--- ids might expect these ids to have a vanilla calling convention even if we
--- determine a different one here.
--- To be able to avoid this we pass a set of boot exported ids for this module around.
--- For non top level ids we can skip this. Local ids are never boot-exported
--- as boot files don't have unfoldings. So there this isn't a concern.
--- See also Note [CBV Function Ids]
-
-
--- See Note [CBV Function Ids]
+{- Note [Attaching CBV Marks to ids]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+See Note [CBV Function Ids: overview] for what is happening here.
+
+During tidy we take the demands on the arguments for any CBV-candidates and
+compute CBV (call-by-value) semantics for each individual argument. The marks
+themselves then are put onto the function id itself. This means the code
+generator can get the full calling convention by only looking at the function
+itself without having to inspect the RHS.
+
+The actual logic is in computeCbvInfo and takes:
+ * The function id
+ * The functions rhs
+And gives us back the function annotated with the marks. We call it in:
+ * tidyTopPair for top level bindings
+ * tidyBind for local bindings.
+
+Wrinkles
+
+(ACBV1) Note that we *have* to look at the untidied rhs. During tidying some
+ knot-tying occurs which can blow up if we look at the post-tidy types of the
+ arguments here. However we only care if the types are unlifted and that
+ doesn't change during tidy. so we can just look at the untidied types.
+
+(ACBV2) If the id is boot-exported we don't use a cbv calling convention via
+ marks, as the boot file won't contain them. Which means code calling
+ boot-exported ids might expect these ids to have a vanilla calling convention
+ even if we determine a different one here.
+
+ To be able to avoid this we pass a set of boot exported ids for this module
+ around. For non top level ids we can skip this. Local ids are never
+ boot-exported as boot files don't have unfoldings. So there this isn't a
+ concern. See also Note [CBV Function Ids: overview]
+-}
+
tidyCbvInfoTop :: HasDebugCallStack => NameSet -> Id -> CoreExpr -> Id
+-- See Note [CBV Function Ids: overview]
tidyCbvInfoTop boot_exports id rhs
- -- Can't change calling convention for boot exported things
- | elemNameSet (idName id) boot_exports = id
- | otherwise = computeCbvInfo id rhs
+ | elemNameSet (idName id) boot_exports
+ = id -- Can't change calling convention for boot exported things
+ -- See (ACBV2) in Note [Attaching CBV Marks to ids]
+ | otherwise
+ = computeCbvInfo id rhs
--- See Note [CBV Function Ids]
tidyCbvInfoLocal :: HasDebugCallStack => Id -> CoreExpr -> Id
+-- See Note [CBV Function Ids: overview]
tidyCbvInfoLocal id rhs = computeCbvInfo id rhs
-- | For a binding we:
@@ -124,9 +124,8 @@ tidyCbvInfoLocal id rhs = computeCbvInfo id rhs
-- - It's argument to a worker and demanded strictly
-- - Unless it's an unlifted type already
-- * Update the id
--- See Note [CBV Function Ids]
+-- See Note [CBV Function Ids: overview]
-- See Note [Attaching CBV Marks to ids]
-
computeCbvInfo :: HasCallStack
=> Id -- The function
-> CoreExpr -- It's RHS
@@ -172,7 +171,7 @@ computeCbvInfo fun_id rhs
| otherwise
= -- pprTraceDebug "computeCbvInfo: Worker seems to take unboxed tuple/sum types!"
-- (ppr fun_id <+> ppr rhs)
- asNonWorkerLikeId fun_id
+ removeCbvCandidate fun_id
-- We don't set CBV marks on functions which take unboxed tuples or sums as
-- arguments. Doing so would require us to compute the result of unarise
@@ -197,7 +196,7 @@ computeCbvInfo fun_id rhs
isSimplePrimRep _ = False
mkMark arg
- | not $ shouldUseCbvForId arg = NotMarkedCbv
+ | not $ wantCbvForId arg = NotMarkedCbv
-- We can only safely use cbv for strict arguments
| (isStrUsedDmd (idDemandInfo arg))
, not (isDeadEndId fun_id) = MarkedCbv
=====================================
compiler/GHC/Core/Unfold.hs
=====================================
@@ -152,10 +152,12 @@ updateCaseScaling n opts = opts { unfoldingCaseScaling = n }
updateReportPrefix :: Maybe String -> UnfoldingOpts -> UnfoldingOpts
updateReportPrefix n opts = opts { unfoldingReportPrefix = n }
-data ArgSummary = TrivArg -- Nothing interesting
- | NonTrivArg -- Arg has structure
- | ValueArg -- Arg is a con-app or PAP
- -- ..or con-like. Note [Conlike is interesting]
+data ArgSummary
+ = TrivArg -- Nothing interesting
+ | NonTrivArg -- Arg has structure
+ | ValueArg -- Arg is a con-app or PAP
+ -- ..or con-like. See (IA1) in Note [Interesting arguments]
+ -- in GHC.Core.Opt.Simplify.Utils
instance Outputable ArgSummary where
ppr TrivArg = text "TrivArg"
@@ -776,7 +778,7 @@ litSize _other = 0 -- Must match size of nullary constructors
-- (eg via case binding)
classOpSize :: UnfoldingOpts -> Class -> [Id] -> [CoreExpr] -> ExprSize
--- See Note [Conlike is interesting]
+-- See (IA1) in Note [Interesting arguments] in GHC.Core.Opt.Simplify.Utils
classOpSize opts cls top_args args
| isUnaryClass cls
= sizeZero -- See (UCM4) in Note [Unary class magic] in GHC.Core.TyCon
=====================================
compiler/GHC/Core/Utils.hs
=====================================
@@ -59,7 +59,7 @@ module GHC.Core.Utils (
isJoinBind,
-- * Tag inference
- mkStrictFieldSeqs, shouldStrictifyIdForCbv, shouldUseCbvForId,
+ mkStrictFieldSeqs, wantCbvForId,
-- * unsafeEqualityProof
isUnsafeEqualityCase,
@@ -1509,6 +1509,23 @@ going to put up with this, because the previous more aggressive inlining
(which treated 'noFactor' as work-free) was duplicating primops, which
in turn was making inner loops of array calculations runs slow (#5623)
+Wrinkles
+
+(WF1) Strict constructor fields. We regard (K x) as work-free even if
+ K is a strict data constructor (see Note [Strict fields in Core])
+ data T a = K !a
+ If we have
+ let t = K x in ...(case t of K y -> blah)...
+ we want to treat t's binding as expandable so that `exprIsConApp_maybe`
+ will look through its unfolding. (NB: exprIsWorkFree implies
+ exprIsExpandable.)
+
+ Note, however, that because K is strict, after inlining we'll get a leftover
+ eval on x, which may or may not disappear
+ let t = K x in ...(case x of y -> blah)...
+ We put up with this extra eval: in effect we count duplicating the eval as
+ work-free.
+
Note [Case expressions are work-free]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Are case-expressions work-free? Consider
@@ -1650,7 +1667,8 @@ isWorkFreeApp fn n_val_args
= True
| otherwise
= case idDetails fn of
- DataConWorkId {} -> True
+ DataConWorkId {} -> True -- Even if the data constructor is strict
+ -- See (WF1) in Note [exprIsWorkFree]
PrimOpId op _ -> primOpIsWorkFree op
_ -> False
@@ -1751,6 +1769,8 @@ expansion. Specifically:
duplicate the (a +# b) primop, which we should not do lightly.
(It's quite hard to trigger this bug, but T13155 does so for GHC 8.0.)
+NB: exprIsWorkFree implies exprIsExpandable.
+
Note [isExpandableApp: bottoming functions]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
It's important that isExpandableApp does not respond True to bottoming
@@ -2901,29 +2921,38 @@ dumpIdInfoOfProgram dump_locals ppr_id_info binds = vcat (map printId ids)
{- Note [Call-by-value for worker args]
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-If we unbox a constructor with strict fields we want to
-preserve the information that some of the arguments came
-out of strict fields and therefore should be already properly
-tagged, however we can't express this directly in core.
-
-Instead what we do is generate a worker like this:
+If we unbox a constructor with strict fields we want to preserve the information
+that some of the arguments came out of strict fields and therefore should be
+already evaluated and properly tagged (EPT) throughout the body of the
+function. We express this fact in Core like this:
data T = MkT A !B
foo = case T of MkT a b -> $wfoo a b
$wfoo a b = case b of b' -> rhs[b/b']
+ ^^^^ The "extra eval"
+
+Now
+ * Throughout `rhs` the Simplifier can see that `b` is EPT, and can (say)
+ drop evals on `b`.
-This makes the worker strict in b causing us to use a more efficient
-calling convention for `b` where the caller needs to ensure `b` is
-properly tagged and evaluated before it's passed to $wfoo. See Note [CBV Function Ids].
+ * The EPT enforcement pass will make $wfoo into a CBV function, where
+ the caller guarantees to pass an EPT argument (see Note [EPT enforcement] in
+ GHC.Core.Stg.EnforceEpt)
-Usually the argument will be known to be properly tagged at the call site so there is
+ * The code generator will discard that "extra eval" case, because $wfoo is
+ CBV.
+
+See also Note [CBV Function Ids: overview].
+
+In tihs case the argument is known to be properly tagged at the call site so there is
no additional work for the caller and the worker can be more efficient since it can
assume the presence of a tag.
This is especially true for recursive functions like this:
-- myPred expect it's argument properly tagged
+ -- The EnforceEPT pass has made it a CBV function
myPred !x = ...
loop :: MyPair -> Int
@@ -2933,11 +2962,10 @@ This is especially true for recursive functions like this:
B -> 2
_ -> loop (MyPair (myPred x) (myPred y))
-Here we would ordinarily not be strict in y after unboxing.
-However if we pass it as a regular argument then this means on
-every iteration of loop we will incur an extra seq on y before
-we can pass it to `myPred` which isn't great! That is in STG after
-tag inference we get:
+Here we would ordinarily not be strict in y after unboxing. However if we pass
+it as a regular argument then this means on every iteration of loop we will
+incur an extra seq on y before we can pass it to `myPred` which isn't great!
+That is in STG after tag inference we get:
Rec {
Find.$wloop [InlPrag=[2], Occ=LoopBreaker]
@@ -2962,7 +2990,7 @@ tag inference we get:
};
end Rec }
-Here comes the tricky part: If we make $wloop strict in both x/y and we get:
+But if we add an extra eval on `y` during worker/wrapper we this this:
Rec {
Find.$wloop [InlPrag=[2], Occ=LoopBreaker]
@@ -2986,18 +3014,24 @@ Here comes the tricky part: If we make $wloop strict in both x/y and we get:
};
end Rec }
-Here both x and y are known to be tagged in the function body since we pass strict worker args using unlifted cbv.
-This means the seqs on x and y both become no-ops and compared to the first version the seq on `y` disappears at runtime.
-
-The downside is that the caller of $wfoo potentially has to evaluate `y` once if we can't prove it isn't already evaluated.
-But y coming out of a strict field is in WHNF so safe to evaluated. And most of the time it will be properly tagged+evaluated
-already at the call site because of the EPT Invariant! See Note [EPT enforcement] for more in this.
-This makes GHC itself around 1% faster despite doing slightly more work! So this is generally quite good.
-
-We only apply this when we think there is a benefit in doing so however. There are a number of cases in which
-it would be useless to insert an extra seq. ShouldStrictifyIdForCbv tries to identify these to avoid churn in the
+Here both x and y are known to be tagged in the function body since we pass
+strict worker args using unlifted cbv. This means the seqs on x and y both
+become no-ops (via (EPT-codegen) in Not [EPT enforcement]) and, compared to the
+first version, the seq on `y` disappears at runtime.
+
+The downside is that the caller of $wfoo potentially has to evaluate `y` once if
+we can't prove it isn't already evaluated. The wrapper, which calls `$wfoo` has
+just pulled `y` out of a strict field of a data constructor, so it will always
+be EPT. See Note [EPT enforcement] for more in this. This makes GHC itself
+around 1% faster despite doing slightly more work! So this is generally quite
+good.
+
+We only apply this when we think there is a benefit in doing so however. There
+are a number of cases in which it would be useless to insert an extra
+seq. `wantCbvForId` tries to identify these to avoid churn in the
simplifier. See Note [Which Ids should be strictified] for details on this.
-}
+
mkStrictFieldSeqs :: [(Id,StrictnessMark)] -> CoreExpr -> (CoreExpr)
mkStrictFieldSeqs args rhs =
foldr addEval rhs args
@@ -3007,7 +3041,7 @@ mkStrictFieldSeqs args rhs =
addEval (arg_id,arg_cbv) (rhs)
-- Argument representing strict field.
| isMarkedStrict arg_cbv
- , shouldStrictifyIdForCbv arg_id
+ , wantCbvForId arg_id
-- Make sure to remove unfoldings here to avoid the simplifier dropping those for OtherCon[] unfoldings.
= Case (Var $! zapIdUnfolding arg_id) arg_id case_ty ([Alt DEFAULT [] rhs])
-- Normal argument
@@ -3027,87 +3061,99 @@ There are multiple reasons why we might not want to insert a seq in the rhs to
strictify a functions argument:
1) The argument doesn't exist at runtime.
-
-For zero width types (like Types) there is no benefit as we don't operate on them
-at runtime at all. This includes things like void#, coercions and state tokens.
+ For zero width types (like Types) there is no benefit as we don't operate on them
+ at runtime at all. This includes things like void#, coercions and state tokens.
2) The argument is a unlifted type.
-
-If the argument is a unlifted type the calling convention already is explicitly
-cbv. This means inserting a seq on this argument wouldn't do anything as the seq
-would be a no-op *and* it wouldn't affect the calling convention.
+ If the argument is a unlifted type the calling convention already is explicitly
+ cbv. This means inserting a seq on this argument wouldn't do anything as the seq
+ would be a no-op *and* it wouldn't affect the calling convention.
3) The argument is absent.
+ If the argument is absent in the body there is no advantage to it being passed as
+ cbv to the function. The function won't ever look at it so we don't save any work.
-If the argument is absent in the body there is no advantage to it being passed as
-cbv to the function. The function won't ever look at it so we don't safe any work.
-
-This mostly happens for join point. For example we might have:
-
- data T = MkT ![Int] [Char]
- f t = case t of MkT xs{strict} ys-> snd (xs,ys)
-
-and abstract the case alternative to:
-
- f t = join j1 = \xs ys -> snd (xs,ys)
- in case t of MkT xs{strict} ys-> j1 xs xy
-
-While we "use" xs inside `j1` it's not used inside the function `snd` we pass it to.
-In short a absent demand means neither our RHS, nor any function we pass the argument
-to will inspect it. So there is no work to be saved by forcing `xs` early.
+ This mostly happens for join points. For example we might have:
-NB: There is an edge case where if we rebox we *can* end up seqing an absent value.
-Note [Absent fillers] has an example of this. However this is so rare it's not worth
-caring about here.
+ data T = MkT ![Int] [Char]
+ f t = case t of MkT xs{strict} ys-> snd (xs,ys)
-4) The argument is already strict.
+ and abstract the case alternative to:
-Consider this code:
+ f t = join j1 = \xs ys -> snd (xs,ys)
+ in case t of MkT xs{strict} ys-> j1 xs xy
- data T = MkT ![Int]
- f t = case t of MkT xs{strict} -> reverse xs
+ While we "use" xs inside `j1` it's not used inside the function `snd` we pass it to.
+ In short a absent demand means neither our RHS, nor any function we pass the argument
+ to will inspect it. So there is no work to be saved by forcing `xs` early.
-The `xs{strict}` indicates that `xs` is used strictly by the `reverse xs`.
-If we do a w/w split, and add the extra eval on `xs`, we'll get
-
- $wf xs =
- case xs of xs1 ->
- let t = MkT xs1 in
- case t of MkT xs2 -> reverse xs2
-
-That's not wrong; but the w/w body will simplify to
-
- $wf xs = case xs of xs1 -> reverse xs1
-
-and now we'll drop the `case xs` because `xs1` is used strictly in its scope.
-Adding that eval was a waste of time. So don't add it for strictly-demanded Ids.
+ NB: There is an edge case where if we rebox we *can* end up seqing an absent value.
+ Note [Absent fillers] has an example of this. However this is so rare it's not worth
+ caring about here.
5) Functions
-
-Functions are tricky (see Note [TagInfo of functions] in EnforceEpt).
-But the gist of it even if we make a higher order function argument strict
-we can't avoid the tag check when it's used later in the body.
-So there is no benefit.
+ Functions are tricky (see Note [TagInfo of functions] in EnforceEpt).
+ But the gist of it even if we make a higher order function argument strict
+ we can't avoid the tag check when it's used later in the body.
+ So there is no benefit.
+
+Wrinkles:
+
+(WIS1) You might have thought that we can omit the eval if the argument is used
+ strictly demanded in the body. But you'd be wrong. Consider this code:
+ data T = MkT ![Int]
+ f t = case t of MkT xs{Dmd=STR} -> reverse xs
+
+ The `xs{Dmd=STR}` indicates that `xs` is used strictly by the `reverse xs`.
+ If we do a w/w split, and add the extra eval on `xs`, we'll get
+ $wf xs = case xs of xs1 ->
+ let t = MkT xs1 in
+ case t of MkT xs2 -> reverse xs2
+
+ That's not wrong; but you might wonder if the eval on `xs` is needed
+ when it is certainly evaluated by the `reverse`. But yes, it is (#26722):
+ g s True t = f s t t
+ g s False t = g s True t
+
+ f True (MkT xs) t = f False (MkT xs) t
+ f False (MkT xs) _ = xs
+
+ After worker/wrapper we get:
+ g s b t = case t of MkT ww -> $wg s b ww
+ $wg s ds ww = case ds of {
+ False -> case ww of wg { __DEFAULT -> Bar.$wg s True wg }
+ True -> let { t1 = MkT ww } in f s t1 t1 }
+
+ We must make `f` inline inside `$wg`, because `f` too is ww'd, and we
+ don't want to rebox `t1` before passing it to `f`. BUT while `t1`
+ looks like a HNF, `exprIsHNF` will say False because `MkT` is strict
+ and `ww` isn't evaluated. So `f` doesn't inline and we get lots of
+ reboxing.
+
+ The Right Thing to to is to add the eval for the data con argument:
+ $wg s ds ww = case ww of ww' { DEFAULT ->
+ case ds of {
+ False -> case ww of wg { __DEFAULT -> Bar.$wg s True wg }
+ True -> let { t1 = MkT ww' } in f s t1 t1 } }
+
+ Now `t1` will be a HNF, and `f` will inline, and we get
+ $wg s ds ww = case ww of ww' { DEFAULT ->
+ case ds of {
+ False -> Bar.$wg s True ww'
+ True -> $wf s ww'
+
+ (Ultimately `$wg` will be a CBV function, so that `case ww` will be a
+ no-op: see (EPT-codegen) in Note [EPT enforcement] in GHC.Stg.EnforceEpt.)
-}
--- | Do we expect there to be any benefit if we make this var strict
--- in order for it to get treated as as cbv argument?
--- See Note [Which Ids should be strictified]
--- See Note [CBV Function Ids] for more background.
-shouldStrictifyIdForCbv :: Var -> Bool
-shouldStrictifyIdForCbv = wantCbvForId False
-
--- Like shouldStrictifyIdForCbv but also wants to use cbv for strict args.
-shouldUseCbvForId :: Var -> Bool
-shouldUseCbvForId = wantCbvForId True
-- When we strictify we want to skip strict args otherwise the logic is the same
--- as for shouldUseCbvForId so we common up the logic here.
+-- as for wantCbvForId so we common up the logic here.
-- Basically returns true if it would be beneficial for runtime to pass this argument
-- as CBV independent of weither or not it's correct. E.g. it might return true for lazy args
-- we are not allowed to force.
-wantCbvForId :: Bool -> Var -> Bool
-wantCbvForId cbv_for_strict v
+wantCbvForId :: Var -> Bool
+wantCbvForId v
-- Must be a runtime var.
-- See Note [Which Ids should be strictified] point 1)
| isId v
@@ -3121,9 +3167,6 @@ wantCbvForId cbv_for_strict v
, not $ isFunTy ty
-- If the var is strict already a seq is redundant.
-- See Note [Which Ids should be strictified] point 4)
- , not (isStrictDmd dmd) || cbv_for_strict
- -- If the var is absent a seq is almost always useless.
- -- See Note [Which Ids should be strictified] point 3)
, not (isAbsDmd dmd)
= True
| otherwise
=====================================
compiler/GHC/CoreToStg/Prep.hs
=====================================
@@ -1582,7 +1582,8 @@ maybeSaturate fn expr n_args unsat_ticks
-- See Note [Eta expansion of hasNoBinding things in CorePrep]
= return $ wrapLamBody (\body -> foldr mkTick body unsat_ticks) sat_expr
- | mark_arity > 0 -- A call-by-value function. See Note [CBV Function Ids]
+ | mark_arity > 0 -- A call-by-value function.
+ -- See Note [CBV Function Ids: overview]
, not applied_marks
= assertPpr
( not (isJoinId fn)) -- See Note [Do not eta-expand join points]
=====================================
compiler/GHC/Stg/EnforceEpt.hs
=====================================
@@ -66,13 +66,13 @@ SG thinks it would be good to fix this; see #21792.
Note [EPT enforcement]
~~~~~~~~~~~~~~~~~~~~~~
The goal of EnforceEPT pass is to mark as many binders as possible as EPT
-(see Note [Evaluated and Properly Tagged]).
-To find more EPT binders, it establishes the following
+(see Note [Evaluated and Properly Tagged]). It establishes the following
+invariant:
EPT INVARIANT:
> Any binder of
> * a strict field (see Note [Strict fields in Core]), or
-> * a CBV argument (see Note [CBV Function Ids])
+> * a CBV argument (see Note [CBV Function Ids: overview])
> is EPT.
(Note that prior to EPT enforcement, this invariant may *not* always be upheld.
@@ -105,7 +105,7 @@ however, we presently only promote worker functions such as $wf to CBV because
we see all its call sites and can use the proper by-value calling convention.
More precisely, with -O0, we guarantee that no CBV functions are visible in
the interface file, so that naïve clients do not need to know how to call CBV
-functions. See Note [CBV Function Ids] for more details.
+functions. See Note [CBV Function Ids: overview] for more details.
Specification
-------------
@@ -140,9 +140,11 @@ Afterwards, the *EPT rewriter* inserts the actual evals realising Upcasts.
Implementation
--------------
-* EPT analysis is implemented in GHC.Stg.EnforceEpt.inferTags.
+(EPT-anal) EPT analysis is implemented in `GHC.Stg.EnforceEpt.inferTags.`
It attaches its result to /binders/, not occurrence sites.
-* The EPT rewriter establishes the EPT invariant by inserting evals. That is, if
+
+(EPT-rewrite) The EPT rewriter, `GHC.Stg.EnforceEpt.Rewrite.rewriteTopBinds`,
+ establishes the EPT invariant by inserting evals. That is, if
(a) a binder x is used to
* construct a strict field (`SP x y`), or
* passed as a CBV argument (`$wf x`),
@@ -152,17 +154,27 @@ Implementation
case x of x' { __ DEFAULT -> SP x' y }.
case x of x' { __ DEFAULT -> $wf x' }.
(Recall that the case binder x' is always EPT.)
- This is implemented in GHC.Stg.EnforceEpt.Rewrite.rewriteTopBinds.
+
This pass also propagates the EPTness from binders to occurrences.
+
It is sound to insert evals on strict fields (Note [Strict fields in Core]),
- and on CBV arguments as well (Note [CBV Function Ids]).
-* We also export the EPTness of top level bindings to allow this optimisation
+ and on CBV arguments as well (Note [CBV Function Ids: overview]).
+
+(EPT-codegen) Finally, code generation for (case x of alts) skips the thunk check
+ when `x` is EPT. This is done (a bit indirectly) thus:
+ * GHC.StgToCmm.Expr.cgCase: builds a `sequel`, and recurses into `cgExpr` on `x`.
+ * When `cgExpr` sees a `x` goes to `cgIdApp`, which uses `getCallMethod`.
+ * Then `getCallMethod` sees that `x` is EPT (via `idTagSigMaybe`), and
+ returns `InferredReturnIt`.
+ * Now `cgIdApp` can jump straight to the case-alternative switch in the `sequel`
+ constructed by `cgCase`.
+
+(EPT-export) We also export the EPTness of top level bindings to allow this optimisation
to work across module boundaries.
+
NB: The EPT Invariant *must* be upheld, regardless of the optimisation level;
hence EPTness is practically part of the internal ABI of a strict data
- constructor or CBV function. Note [CBV Function Ids] contains the details.
-* Finally, code generation skips the thunk check when branching on binders that
- are EPT. This is done by `cgExpr`/`cgCase` in the backend.
+ constructor or CBV function. Note [CBV Function Ids: overview] has the details.
Evaluation
----------
=====================================
compiler/GHC/Stg/Lint.hs
=====================================
@@ -420,7 +420,7 @@ lintAppCbvMarks e@(StgApp fun args) = do
when (lf_unarised lf) $ do
-- A function which expects a unlifted argument as n'th argument
-- always needs to be applied to n arguments.
- -- See Note [CBV Function Ids].
+ -- See Note [CBV Function Ids: overview].
let marks = fromMaybe [] $ idCbvMarks_maybe fun
when (length (dropWhileEndLE (not . isMarkedCbv) marks) > length args) $ do
addErrL $ hang (text "Undersatured cbv marked ID in App" <+> ppr e ) 2 $
=====================================
compiler/GHC/StgToCmm/Closure.hs
=====================================
@@ -617,12 +617,15 @@ getCallMethod cfg name id (LFThunk _ _ updatable std_form_info is_fun)
getCallMethod cfg name id (LFUnknown might_be_a_function) n_args _cg_locs _self_loop_info
| n_args == 0
, Just sig <- idTagSig_maybe id
- , isTaggedSig sig -- Infered to be already evaluated by EPT analysis
- -- When profiling we must enter all potential functions to make sure we update the SCC
- -- even if the function itself is already evaluated.
+ , isTaggedSig sig -- This `id` is evaluated and properly tagged; no need to enter it
+ -- See (EPT-codegen) in Note [EPT enforcement] in GHC.Stg.EnforceEpt
+
+ -- When profiling we must enter all potential functions to make sure we update
+ -- the SCC even if the function itself is already evaluated.
-- See Note [Evaluating functions with profiling] in rts/Apply.cmm
, not (profileIsProfiling (stgToCmmProfile cfg) && might_be_a_function)
- = InferedReturnIt -- See Note [EPT enforcement]
+
+ = InferedReturnIt -- See (EPT-codegen) in Note [EPT enforcement]
| might_be_a_function = SlowCall
=====================================
compiler/GHC/StgToCmm/Expr.hs
=====================================
@@ -1053,6 +1053,7 @@ cgIdApp fun_id args = do
| otherwise -> emitReturn [fun]
-- A value infered to be in WHNF, so we can just return it.
+ -- See (EPT-codegen) in Note [EPT enforcement] in GHC.Stg.EnforceEpt
InferedReturnIt
| isZeroBitTy (idType fun_id) -> trace >> emitReturn []
| otherwise -> trace >> assertTag >>
=====================================
compiler/GHC/Types/Id.hs
=====================================
@@ -117,7 +117,7 @@ module GHC.Types.Id (
setIdCbvMarks,
idCbvMarks_maybe,
idCbvMarkArity,
- asWorkerLikeId, asNonWorkerLikeId,
+ setCbvCandidate, removeCbvCandidate,
idDemandInfo,
idDmdSig,
@@ -563,7 +563,7 @@ isDataConId id = case Var.idDetails id of
-- | An Id for which we might require all callers to pass strict arguments properly tagged + evaluated.
--
--- See Note [CBV Function Ids]
+-- See Note [CBV Function Ids: overview]
isWorkerLikeId :: Id -> Bool
isWorkerLikeId id = case Var.idDetails id of
WorkerLikeId _ -> True
@@ -668,19 +668,20 @@ idJoinArity id = case idJoinPointHood id of
NotJoinPoint -> pprPanic "idJoinArity" (ppr id)
asJoinId :: Id -> JoinArity -> JoinId
-asJoinId id arity = warnPprTrace (not (isLocalId id))
- "global id being marked as join var" (ppr id) $
- warnPprTrace (not (is_vanilla_or_join id))
- "asJoinId"
- (ppr id <+> pprIdDetails (idDetails id)) $
- id `setIdDetails` JoinId arity (idCbvMarks_maybe id)
+asJoinId id arity
+ = warnPprTrace (not (isLocalId id))
+ "global id being marked as join var" (ppr id) $
+ id `setIdDetails` JoinId arity cbv_info
where
- is_vanilla_or_join id = case Var.idDetails id of
- VanillaId -> True
- -- Can workers become join ids? Yes!
- WorkerLikeId {} -> pprTraceDebug "asJoinId (call by value function)" (ppr id) True
- JoinId {} -> True
- _ -> False
+ cbv_info = case Var.idDetails id of
+ VanillaId -> Nothing
+ WorkerLikeId marks -> Just marks
+ JoinId _ mb_marks -> mb_marks
+ _ -> pprTraceDebug "asJoinId"
+ (ppr id <+> pprIdDetails (idDetails id)) $
+ Nothing
+ -- Can workers become join ids? Yes!
+ -- See Note [CBV Function Ids: overview] in GHC.Types.Id.Info
zapJoinId :: Id -> Id
-- May be a regular id already
@@ -691,7 +692,7 @@ zapJoinId jid | isJoinId jid = zapIdTailCallInfo (newIdDetails `seq` jid `setIdD
where
newIdDetails = case idDetails jid of
-- We treat join points as CBV functions. Even after they are floated out.
- -- See Note [Use CBV semantics only for join points and workers]
+ -- See Note [Which Ids should be CBV candidates?]
JoinId _ (Just marks) -> WorkerLikeId marks
JoinId _ Nothing -> WorkerLikeId []
_ -> panic "zapJoinId: newIdDetails can only be used if Id was a join Id."
@@ -840,7 +841,7 @@ setIdCbvMarks id marks
-- Perhaps that's sensible but for now be conservative.
-- Similarly we don't need any lazy marks at the end of the list.
-- This way the length of the list is always exactly number of arguments
- -- that must be visible to CodeGen. See See Note [CBV Function Ids]
+ -- that must be visible to CodeGen. See Note [CBV Function Ids: overview]
-- for more details.
trimmedMarks = dropWhileEndLE (not . isMarkedCbv) $ take (idArity id) marks
@@ -855,18 +856,10 @@ idCbvMarks_maybe id = case idDetails id of
idCbvMarkArity :: Id -> Arity
idCbvMarkArity fn = maybe 0 length (idCbvMarks_maybe fn)
--- | Remove any cbv marks on arguments from a given Id.
-asNonWorkerLikeId :: Id -> Id
-asNonWorkerLikeId id =
- let details = case idDetails id of
- WorkerLikeId{} -> Just $ VanillaId
- JoinId arity Just{} -> Just $ JoinId arity Nothing
- _ -> Nothing
- in maybeModifyIdDetails details id
-
--- | Turn this id into a WorkerLikeId if possible.
-asWorkerLikeId :: Id -> Id
-asWorkerLikeId id =
+-- | Make this Id into a candidate for CBV treatment, if possible.
+-- See Note [CBV Function Ids: overview] in GHC.Types.Id.Info
+setCbvCandidate :: Id -> Id
+setCbvCandidate id =
let details = case idDetails id of
WorkerLikeId{} -> Nothing
JoinId _arity Just{} -> Nothing
@@ -875,6 +868,16 @@ asWorkerLikeId id =
_ -> Nothing
in maybeModifyIdDetails details id
+-- | Remove any CBV-candidate info from a given Id.
+-- See Note [CBV Function Ids: overview] in GHC.Types.Id.Info
+removeCbvCandidate :: Id -> Id
+removeCbvCandidate id =
+ let details = case idDetails id of
+ WorkerLikeId{} -> Just $ VanillaId
+ JoinId arity Just{} -> Just $ JoinId arity Nothing
+ _ -> Nothing
+ in maybeModifyIdDetails details id
+
setCaseBndrEvald :: StrictnessMark -> Id -> Id
-- Used for variables bound by a case expressions, both the case-binder
-- itself, and any pattern-bound variables that are argument of a
=====================================
compiler/GHC/Types/Id/Info.hs
=====================================
@@ -208,14 +208,14 @@ data IdDetails
-- ^ An 'Id' for a join point taking n arguments
-- Note [Join points] in "GHC.Core"
-- Can also work as a WorkerLikeId if given `CbvMark`s.
- -- See Note [CBV Function Ids]
+ -- See Note [CBV Function Ids: overview]
-- The [CbvMark] is always empty (and ignored) until after Tidy.
| WorkerLikeId [CbvMark]
-- ^ An 'Id' for a worker like function, which might expect some arguments to be
-- passed both evaluated and tagged.
-- Worker like functions are create by W/W and SpecConstr and we can expect that they
-- aren't used unapplied.
- -- See Note [CBV Function Ids]
+ -- See Note [CBV Function Ids: overview]
-- See Note [EPT enforcement]
-- The [CbvMark] is always empty (and ignored) until after Tidy for ids from the current
-- module.
@@ -244,85 +244,114 @@ conLikesRecSelInfo con_likes lbls
has_fld dc lbl = any (\ fl -> flLabel fl == lbl) (conLikeFieldLabels dc)
-{- Note [CBV Function Ids]
-~~~~~~~~~~~~~~~~~~~~~~~~~~
-A WorkerLikeId essentially allows us to constrain the calling convention
-for the given Id. Each such Id carries with it a list of CbvMarks
-with each element representing a value argument. Arguments who have
-a matching `MarkedCbv` entry in the list need to be passed evaluated+*properly tagged*.
-
-CallByValueFunIds give us additional expressiveness which we use to improve
-runtime. This is all part of the EPT enforcement work. See also Note [EPT enforcement].
-
-They allows us to express the fact that an argument is not only evaluated to WHNF once we
-entered it's RHS but also that an lifted argument is already *properly tagged* once we jump
-into the RHS.
-This means when e.g. branching on such an argument the RHS doesn't needed to perform
-an eval check to ensure the argument isn't an indirection. All seqs on such an argument in
-the functions body become no-ops as well.
-
-The invariants around the arguments of call by value function like Ids are then:
-
-* In any call `(f e1 .. en)`, if `f`'s i'th argument is marked `MarkedCbv`,
- then the caller must ensure that the i'th argument
- * points directly to the value (and hence is certainly evaluated before the call)
- * is a properly tagged pointer to that value
-
-* The following functions (and only these functions) have `CbvMarks`:
- * Any `WorkerLikeId`
- * Some `JoinId` bindings.
-
-This works analogous to the EPT Invariant. See also Note [EPT enforcement].
-
-To make this work what we do is:
-* During W/W and SpecConstr any worker/specialized binding we introduce
- is marked as a worker binding by `asWorkerLikeId`.
-* W/W and SpecConstr further set OtherCon[] unfoldings on arguments which
- represent contents of a strict fields.
-* During Tidy we look at all bindings.
- For any callByValueLike Id and join point we mark arguments as cbv if they
- Are strict. We don't do so for regular bindings.
- See Note [Use CBV semantics only for join points and workers] for why.
- We might have made some ids rhs *more* strict in order to make their arguments
- be passed CBV. See Note [Call-by-value for worker args] for why.
-* During CorePrep calls to CallByValueFunIds are eta expanded.
+{- Note [CBV Function Ids: overview]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+GHC can decide to use a call-by-value (CBV) calling convention for
+(some arguments of) a function, implying that:
+
+* The caller /must/ pass an argument that is evaluated and properly
+ tagged (EPT). See Note [Evaluated and Properly Tagged] in GHC.Stg.EnforceEpt.
+
+* The function may /assume/ that the argument is EPT, and thereby omit
+ evals that would otherwise be necessary.
+
+CBV-ness is part of the calling convention; it is not optional. If a function
+is compiled with CBV arguments, callers /must/ respect it, else seg-fault
+beckon.
+
+Apart from the more efficent calling convention, a compelling reason for
+a CBV calling conventions is worker-functions for strict data types.
+Example:
+ data T a = MkT ![a]
+ f :: T Int -> blah
+ f (MkT y) = ...
+We get a w/w split
+ $wf y = let x = MkT y in ...
+ f x = case x of MkT y -> $wf y
+But in `$wf`, in general, we'd need to evaluate `y`, becuase `MkT` is strict.
+With a CBV calling convention we can drop that stupid extra eval.
+
+Here's how it all works:
+
+* We identify some function Ids as "CBV candidates";
+ see Note [Which Ids should be CBV candidates?]
+
+* During W/W and SpecConstr: any worker/specialized binding we introduce
+ is marked as a CBV-candidate by `asCbvCandidate`. This simply marks
+ the binding as a candidate for CBV-ness, using IdDetails `WorkerLikeId []`.
+ See Note [Which Ids should be CBV candidates?].
+
+ See also Note [Call-by-value for worker args] for how we build the worker RHS.
+
+* A CBV candidate may become a join point; we are careful to retain
+ its CBV-candidature; see `GHC.Types.Id.asJoinId`. (Actually that hardly
+ matters because all join points are CBV-candidates.) A join point can also
+ become an ordinary Id, due to floating (see `zapJoinId`); again we are
+ careful to retain CBV-candidature.
+
+* During Tidy, for CBV-candidate Ids, including join points, we mark any
+ /strict/ arguments as CBV. This is the point at which the CbvMarks inside a
+ WorkerLikeId are set. See `GHC.Core.Tidy.computeCbvInfo`, and
+
+ This step is informed by a late demand analysis, performed just before tidying
+ to identify strict arguments. See Note [Call-by-value for worker args] for
+ how a worker guarantees to be strict in strict datacon fields.
+
+ TODO: We currently don't do this for arguments that are unboxed sums or tuples,
+ because then we'd have to predict the result of unarisation. But it would be nice to
+ do so. See `computeCbvInfo`.
+
+* During CorePrep calls to CBV Ids are eta expanded.
+ See `GHC.CoreToStg.Prep.maybeSaturate`.
+
* During Stg CodeGen:
* When we see a call to a callByValueLike Id:
* We check if all arguments marked to be passed unlifted are already tagged.
* If they aren't we will wrap the call in case expressions which will evaluate+tag
these arguments before jumping to the function.
+ See (EPT-rewrite) in Note [EPT enforcement] in GHC.Stg.EnforceEpt
+
* During Cmm codeGen:
* When generating code for the RHS of a StrictWorker binding
we omit tag checks when using arguments marked as tagged.
+ See (EPT-codegen) in Note [EPT enforcement] in GHC.Stg.EnforceEpt
+
+* Imported functions may be CBV, and then there is no point in eta-reducing
+ them; we'll just have to eta-expand later; see GHC.Core.Opt.Arity.cantEtaReduceFun.
+*** SPJ really? Andreas? ****
We only use this for workers and specialized versions of SpecConstr
But we also check other functions during tidy and potentially turn some of them into
call by value functions and mark some of their arguments as call-by-value by looking at
argument unfoldings.
-NB: I choose to put the information into a new Id constructor since these are loaded
-at all optimization levels. This makes it trivial to ensure the additional
-calling convention demands are available at all call sites. Putting it into
-IdInfo would require us at the very least to always decode the IdInfo
+
+NB: I choose to put the CBV information into the IdDetails since these are
+loaded at all optimization levels. This makes it trivial to ensure the
+additional calling convention demands are available at all call sites. Putting
+it into IdInfo would require us at the very least to always decode the IdInfo
just to decide if we need to throw it away or not after.
-Note [Use CBV semantics only for join points and workers]
-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-A function with cbv-semantics requires arguments to be visible
-and if no arguments are visible requires us to eta-expand it's
-call site. That is for a binding with three cbv arguments like
-`w[WorkerLikeId[!,!,!]]` we would need to eta expand undersaturated
-occurrences like `map w xs` into `map (\x1 x2 x3 -> w x1 x2 x3) xs.
-
-In experiments it turned out that the code size increase of doing so
-can outweigh the performance benefits of doing so.
-So we only do this for join points, workers and
-specialized functions (from SpecConstr).
-Join points are naturally always called saturated so
-this problem can't occur for them.
-For workers and specialized functions there are also always at least
-some applied arguments as we won't inline the wrapper/apply their rule
-if there are unapplied occurrences like `map f xs`.
+Note [Which Ids should be CBV candidates?]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+In principle, we could use a CBV calling convention for /any/ strict function.
+But when we use CBV semantics the caller must obey the EPT calling convention,
+and that may mean eta-expansion. For example, for a binding with three CBV
+arguments like `foo[WorkerLikeId[!,!,!]]` we would need to eta expand undersaturated
+occurrences like `map foo xs` into `map (\x1 x2 x3 -> w x1 x2 x3) xs.
+
+In experiments it turned out that the code size increase of doing so can
+outweigh the performance benefits of doing so.
+
+So we treat only certain functions as candidates for CBV treatment:
+ * Workers created by worker/wrapper.
+ * Specialised functions from SpecConstr
+ * Join points
+
+Reason:
+ * All of these are always called saturated (at birth anyway)
+ * For workers in particular we want to use CBV for strict
+ fields of data constructors
-}
-- | Parent of a record selector function.
=====================================
compiler/GHC/Types/Id/Make.hs
=====================================
@@ -1038,7 +1038,7 @@ until the final simplifier phase; see Note [Activation for data
constructor wrappers].
For further reading, see:
- * Note [Conlike is interesting] in GHC.Core.Op.Simplify.Utils
+ * (IA1) in Note [Interesting arguments] in GHC.Core.Op.Simplify.Utils
* Note [Lone variables] in GHC.Core.Unfold
* Note [exprIsConApp_maybe on data constructors with wrappers]
in GHC.Core.SimpleOpt
=====================================
testsuite/tests/simplCore/should_compile/T18013.stderr
=====================================
@@ -143,14 +143,14 @@ T18013.$wmapMaybeRule [InlPrag=NOINLINE]
Unf=OtherCon []]
T18013.$wmapMaybeRule
= \ (@a) (@b) (@s) (ww :: s) (ww1 :: s -> a -> IO (Result s b)) ->
+ case ww of ww2 { __DEFAULT ->
case ww1 of wild { __DEFAULT ->
- case ww of wild1 { __DEFAULT ->
T18013a.Rule
@IO
@(Maybe a)
@(Maybe b)
@s
- wild1
+ ww2
((\ (s2 :: s)
(a1 :: Maybe a)
(s1 :: GHC.Internal.Prim.State# GHC.Internal.Prim.RealWorld) ->
@@ -158,7 +158,7 @@ T18013.$wmapMaybeRule
Nothing ->
(# s1,
T18013a.Result
- @s @(Maybe b) wild1 (GHC.Internal.Maybe.Nothing @b) #);
+ @s @(Maybe b) ww2 (GHC.Internal.Maybe.Nothing @b) #);
Just x ->
case ((wild s2 x)
`cast` <Co:4> :: IO (Result s b)
=====================================
testsuite/tests/simplCore/should_compile/T26722.hs
=====================================
@@ -0,0 +1,9 @@
+module T26722 where
+
+data T = MkT ![Int]
+
+g s True t = f s t t
+g s False t = g s True t
+
+f True (MkT xs) t = f False (MkT xs) t
+f False (MkT xs) _ = xs
=====================================
testsuite/tests/simplCore/should_compile/T26722.stderr
=====================================
@@ -0,0 +1 @@
+
\ No newline at end of file
=====================================
testsuite/tests/simplCore/should_compile/all.T
=====================================
@@ -575,3 +575,6 @@ test('T26682', normal, multimod_compile, ['T26682', '-O -v0'])
# In the bug report #26615, the overloaded calls were signalled by a dictionary
# argument like fEqList_xxxx, so we grep for that. Not a very robust test
test('T26615', [grep_errmsg(r'fEqList')], multimod_compile, ['T26615', '-O -fspec-constr -ddump-simpl -dsuppress-uniques'])
+
+# T26722: there should be no reboxing in $wg
+test('T26722', [grep_errmsg(r'SPEC')], compile, ['-O -dno-typeable-binds'])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5e1cd595b98fc153beaea795ee079f…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/5e1cd595b98fc153beaea795ee079f…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/spj-unf-size] 78 commits: [#26183] Associated Type Iface Fix
by Simon Peyton Jones (@simonpj) 16 Jan '26
by Simon Peyton Jones (@simonpj) 16 Jan '26
16 Jan '26
Simon Peyton Jones pushed to branch wip/spj-unf-size at Glasgow Haskell Compiler / GHC
Commits:
8a317b6f by Aaron Allen at 2026-01-01T03:05:15-05:00
[#26183] Associated Type Iface Fix
When determining "extras" for class decl interface entries, axioms for
the associated types need to included so that dependent modules will be
recompiled if those axioms change.
resolves #26183
- - - - -
ae1aeaab by Cheng Shao at 2026-01-01T03:06:32-05:00
testsuite: run numeric tests with optasm when available
This patch adds the `optasm` extra way to nueric tests when NCG is
available. Some numeric bugs only surface with optimization, omitting
this can hide these bugs and even make them slip into release! (e.g. #26711)
- - - - -
6213bb57 by maralorn at 2026-01-02T16:30:32+01:00
GHC.Internal.Exception.Context: Fix comment
on addExceptionAnnotation
- - - - -
b820ff50 by Janis Voigtlaender at 2026-01-05T02:43:18-05:00
GHC.Internal.Control.Monad.replicateM: Fix comment
- - - - -
a8a94aad by Cheng Shao at 2026-01-05T16:24:04-05:00
hadrian: drops unused PE linker script for windows
This patch drops unused PE linker script for windows in the
`MergeObjects` builder of hadrian. The linker script is used for
merging object files into a single `HS*.o` object file and undoing the
effect of split sections, when building the "ghci library" object
file. However, we don't build the ghci library on windows, and this
code path is actually unreachable.
- - - - -
53038ea9 by Cheng Shao at 2026-01-05T16:24:04-05:00
hadrian: drop unused logic for building ghci libraries
This patch drops the unused logic for building ghci libraries in
hadrian:
- The term "ghci library" refers to an optional object file per
library `HS*.o`, which is merged from multiple object files in that
library using the `MergeObjects` builder in hadrian.
- The original rationale of having a ghci library object, in addition
to normal archives, was to speedup ghci loading, since the combined
object is linked with a linker script to undo the effects of
`-fsplit-sections` to reduce section count and make it easier for
the RTS linker to handle.
- However, most GHC builds enable `dynamicGhcPrograms` by default, in
such cases the ghci library would already not be built.
- `dynamicGhcPrograms` is disabled on Windows, but still we don't
build the ghci library due to lack of functioning merge objects
command.
- The only case that we actually build ghci library objects, are
alpine fully static bindists. However, for other reasons, split
sections is already disabled for fully static builds anyway!
- There will not be any regression if the ghci library objects are
absent from a GHC global libdir when `dynamicGhcPrograms` is
disabled. The RTS linker can already load the archives without any
issue.
Hence the removal. We now forcibly disable ghci libraries for all
Cabal components, and rip out all logic related to `MergeObjects` and
ghci libraries in hadrian. This also nicely cleans up some old todos
and fixmes that are no longer relevant.
Note that MergeObjects in hadrian is not the same thing as merge
objects in the GHC driver. The latter is not affected by this patch.
-------------------------
Metric Decrease:
libdir
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
8f209336 by Simon Jakobi at 2026-01-05T16:24:48-05:00
User's guide: Fix link to language extensions
Instead of linking to haddocks, it seemed more useful to link
to the extension overview in the user's guide.
Closes #26614.
- - - - -
0b7df6db by Simon Peyton Jones at 2026-01-06T09:32:23-05:00
Improved fundeps for closed type families
The big payload of this commit is to execute the plan suggested
in #23162, by improving the way that we generate functional
dependencies for closed type families.
It is all described in Note [Exploiting closed type families]
Most of the changes are in GHC.Tc.Solver.FunDeps
Other small changes
* GHC.Tc.Solver.bumpReductionDepth. This function brings together the code that
* Bumps the depth
* Checks for overflow
Previously the two were separated, sometimes quite widely.
* GHC.Core.Unify.niFixSubst: minor improvement, removing an unnecessary
itraetion in the base case.
* GHC.Core.Unify: no need to pass an InScopeSet to
tcUnifyTysForInjectivity. It can calculate one for itself; and it is
never inspected anyway so it's free to do so.
* GHC.Tc.Errors.Ppr: slight impovement to the error message for
reduction-stack overflow, when a constraint (rather than a type) is
involved.
* GHC.Tc.Solver.Monad.wrapUnifier: small change to the API
- - - - -
fde8bd88 by Simon Peyton Jones at 2026-01-06T09:32:23-05:00
Add missing (KK4) to kick-out criteria
There was a missing case in kick-out that meant we could fail
to solve an eminently-solvable constraint.
See the new notes about (KK4)
- - - - -
00082844 by Simon Peyton Jones at 2026-01-06T09:32:23-05:00
Some small refactorings of error reporting in the typechecker
This is just a tidy-up commit.
* Add ei_insoluble to ErrorItem, to cache insolubility.
Small tidy-up.
* Remove `is_ip` and `mkIPErr` from GHC.Tc.Errors; instead enhance mkDictErr
to handle implicit parameters. Small refactor.
- - - - -
fe4cb252 by Simon Peyton Jones at 2026-01-06T09:32:24-05:00
Improve recording of insolubility for fundeps
This commit addresses #22652, by recording when the fundeps for
a constraint are definitely insoluble. That in turn improves the
perspicacity of the pattern-match overlap checker.
See Note [Insoluble fundeps]
- - - - -
df0ffaa5 by Simon Peyton Jones at 2026-01-06T09:32:24-05:00
Fix a buglet in niFixSubst
The MR of which this is part failed an assertion check extendTvSubst
because we extended the TvSubst with a CoVar. Boo.
This tiny patch fixes it, and adds the regression test from #13882
that showed it up.
- - - - -
3d6aba77 by konsumlamm at 2026-01-06T09:33:16-05:00
Fix changelog formatting
- - - - -
69e0ab59 by Cheng Shao at 2026-01-06T19:37:56-05:00
compiler: add targetHasRTSWays function
This commit adds a `targetHasRTSWays` util function in
`GHC.Driver.Session` to query if the target RTS has a given Ways (e.g.
WayThreaded).
- - - - -
25a0ab94 by Cheng Shao at 2026-01-06T19:37:56-05:00
compiler: link on-demand external interpreter with threaded RTS
This commit makes the compiler link the on-demand external interpreter
program with threaded RTS if it is available in the target RTS ways.
This is a better default than the previous single-threaded RTS, and it
enables the external interpreter to benefit from parallelism when
deserializing CreateBCOs messages.
- - - - -
92404a2b by Cheng Shao at 2026-01-06T19:37:56-05:00
hadrian: link iserv with threaded RTS
This commit makes hadrian link iserv with threaded RTS if it's
available in the RTS ways. Also cleans up the iserv main C program
which can be replaced by the `-fkeep-cafs` link-time option.
- - - - -
a20542d2 by Cheng Shao at 2026-01-06T19:38:38-05:00
ghc-internal: remove unused GMP macros
This patch removes unused GMP related macros from `ghc-internal`. The
in-tree GMP version was hard coded and outdated, but it was not used
anywhere anyway.
- - - - -
4079dcd6 by Cheng Shao at 2026-01-06T19:38:38-05:00
hadrian: fix in-tree gmp configure error on newer c compilers
Building in-tree gmp on newer c compilers that default to c23 fails at
configure stage, this patch fixes it, see added comment for
explanation.
- - - - -
414d1fe1 by Cheng Shao at 2026-01-06T19:39:20-05:00
compiler: fix LLVM backend pdep/pext handling for i386 target
This patch fixes LLVM backend's pdep/pext handling for i386 target,
and also removes non-existent 128/256/512 bit hs_pdep/hs_pext callees.
See amended note for more explanation. Fixes #26450.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
c7f6fba3 by Cheng Shao at 2026-01-06T19:39:20-05:00
ci: remove allow_failure flag for i386 alpine job
The LLVM codegen issue for i386 has been fixed, and the i386 alpine
job should pass now. This commit removes the allow_failure flag so
that other i386 regressions in the future are signaled more timely.
- - - - -
52d00c05 by Simon Peyton Jones at 2026-01-07T10:24:21-05:00
Add missing InVar->OutVar lookup in SetLevels
As #26681 showed, the SetLevels pass was failing to map an InVar to
an OutVar. Very silly! I'm amazed it hasn't broken before now.
I have improved the type singatures (to mention InVar and OutVar)
so it's more obvious what needs to happen.
- - - - -
ab0a5594 by Cheng Shao at 2026-01-07T10:25:04-05:00
hadrian: drop deprecated pkgHashSplitObjs code path
This patch drops deprecated `pkgHashSplitObjs` code path from hadrian,
since GHC itself has removed split objs support many versions ago and
this code path is unused.
- - - - -
bb3a2ba1 by Cheng Shao at 2026-01-07T10:25:44-05:00
hadrian: remove linting/assertion in quick-validate flavour
The `quick-validate` flavour is meant for testing ghc and passing the
testsuite locally with similar settings to `validate` but faster. This
patch removes the linting/assertion overhead in `quick-validate` to
improve developer experience. I also took the chance to simplify
redundant logic of rts/library way definition in `validate` flavour.
- - - - -
7971f5dd by Cheng Shao at 2026-01-07T10:26:26-05:00
deriveConstants: clean up unused constants
This patch cleans up unused constants from `deriveConstants`, they are
not used by C/Cmm code in the RTS, nor compiler-generated code.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
4df96993 by Cheng Shao at 2026-01-07T10:27:08-05:00
hadrian: pass -fno-omit-frame-pointer with +debug_info
This patch adds `-fno-omit-frame-pointer` as C/C++ compilation flag
when compiling with `+debug_info` flavour transformer. It's a sane
default when you care about debugging and reliable backtraces, and
makes debugging/profiling with bpf easier.
- - - - -
8a3900a3 by Aaron Allen at 2026-01-07T10:27:57-05:00
[26705] Include TyCl instances in data fam iface entry
Ensures dependent modules are recompiled when the class instances for a
data family instance change.
resolves #26705
- - - - -
a0b980af by Cheng Shao at 2026-01-07T10:28:38-05:00
hadrian: remove unused Hp2Ps/Hpc builders
This patch removes the Hp2Ps/Hpc builders from hadrian, they are
unused in the build system. Note that the hp2ps/hpc programs are still
built and not affected.
- - - - -
50a58757 by Cheng Shao at 2026-01-07T10:29:20-05:00
hadrian: only install js files to libdir for wasm/js targets
There are certain js files required for wasm/js targets to work, and
previously hadrian would install those js files to libdir
unconditionally on other targets as well. This could be a minor
annoyance for packagers especially when the unused js files contain
shebangs that interfere with the packaging process. This patch makes
hadrian only selectively install the right js files for the right
targets.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
da40e553 by Simon Peyton Jones at 2026-01-07T10:30:00-05:00
Add flavour transformer assertions_stage1
This allows us to enable -DDEBUG assertions in the stage1 compiler
- - - - -
ec3cf767 by Cheng Shao at 2026-01-08T06:24:31-05:00
make: remove unused Makefiles from legacy make build system
This patch removes unused Makefiles from legacy make build system; now
they are never used by hadrian in any way, and they already include
common boilerplate mk files that are long gone in the make build
system removal, hence the housecleaning.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
04ea3f83 by Cheng Shao at 2026-01-08T06:25:13-05:00
compiler: use -O3 as LLVM optimization level for ghc -O2
The GHC driver clamps LLVM optimization level to `-O2` due to LLVM
crashes, but those were historical issues many years ago that are no
longer relevant for LLVM versions we support today. This patch changes
the driver to use `-O3` as LLVM optimization level when compiling with
`-O2`, which is a better default when we're willing to trade
compilation time for faster generated code.
- - - - -
472df471 by Peter Trommler at 2026-01-08T13:28:54-05:00
Use half-word literals in info tables
With this commit info tables are mapped to the same assembler code
on big-endian and little-endian platforms.
Fixes #26579.
- - - - -
393f9c51 by Simon Peyton Jones at 2026-01-08T13:29:35-05:00
Refactor srutOkForBinderSwap
This MR does a small refactor:
* Moves `scrutOkForBinderSwap` and `BinderSwapDecision`
to GHC.Core.Utils
* Inverts the sense of the coercion it returns, which makes
more sense
No effect on behaviour
- - - - -
ad76fb0f by Simon Peyton Jones at 2026-01-08T13:29:36-05:00
Improve case merging
This small MR makes case merging happen a bit more often than
it otherwise could, by getting join points out of the way.
See #26709 and GHC.Core.Utils
Note [Floating join points out of DEFAULT alternatives]
- - - - -
4c9395f5 by Cheng Shao at 2026-01-08T13:30:16-05:00
hadrian: remove broken hsc2hs flag when cross compiling to windows
This patch removes the `--via-asm` hsc2hs flag when cross compiling to
windows. With recent llvm-mingw toolchain, it would fail with:
```
x86_64-w64-mingw32-hsc2hs: Cannot combine instructions: [Quad 8,Long 4,Long 241,Ref ".Ltmp1-.Ltmp0"]
```
The hsc2hs default `--cross-compile` logic is slower but works.
- - - - -
71fdef55 by Simon Peyton Jones at 2026-01-08T13:30:57-05:00
Try harder to keep the substitution empty
Avoid unnecessary cloning of variables in the Simplifier.
Addresses #26724,
See Note [Keeping the substitution empty]
We get some big wins in compile time
Metrics: compile_time/bytes allocated
-------------------------------------
Baseline
Test Metric value New value Change
----------------------------------------------------------------------------
CoOpt_Singletons(normal) ghc/alloc 721,544,088 692,174,216 -4.1% GOOD
LargeRecord(normal) ghc/alloc 1,268,031,157 1,265,168,448 -0.2%
T14766(normal) ghc/alloc 918,218,533 688,432,296 -25.0% GOOD
T15703(normal) ghc/alloc 318,103,629 306,638,016 -3.6% GOOD
T17836(normal) ghc/alloc 419,174,584 418,400,824 -0.2%
T18478(normal) ghc/alloc 471,042,976 470,261,376 -0.2%
T20261(normal) ghc/alloc 573,387,162 563,663,336 -1.7%
T24984(normal) ghc/alloc 87,832,666 87,636,168 -0.2%
T25196(optasm) ghc/alloc 1,103,284,040 1,101,376,992 -0.2%
hard_hole_fits(normal) ghc/alloc 224,981,413 224,608,208 -0.2%
geo. mean -0.3%
minimum -25.0%
maximum +0.1%
Metric Decrease:
CoOpt_Singletons
T14766
T15703
- - - - -
30341168 by Simon Peyton Jones at 2026-01-08T13:31:38-05:00
Add regression test for #24867
- - - - -
1ac1a541 by Julian Ospald at 2026-01-09T02:48:53-05:00
Support statically linking executables properly
Fixes #26434
In detail, this does a number of things:
* Makes GHC aware of 'extra-libraries-static' (this changes the package
database format).
* Adds a switch '-static-external' that will honour 'extra-libraries-static'
to link external system dependencies statically.
* Adds a new field to settings/targets: "ld supports verbatim namespace".
This field is used by '-static-external' to conditionally use '-l:foo.a'
syntax during linking, which is more robust than trying to find the
absolute path to an archive on our own.
* Adds a switch '-fully-static' that is meant as a high-level interface
for e.g. cabal. This also honours 'extra-libraries-static'.
This also attempts to clean up the confusion around library search directories.
At the moment, we have 3 types of directories in the package database
format:
* library-dirs
* library-dirs-static
* dynamic-library-dirs
However, we only have two types of linking: dynamic or static. Given the
existing logic in 'mungeDynLibFields', this patch assumes that
'library-dirs' is really just nothing but a fallback and always
prefers the more specific variants if they exist and are non-empty.
Conceptually, we should be ok with even just one search dirs variant.
Haskell libraries are named differently depending on whether they're
static or dynamic, so GHC can conveniently pick the right one depending
on the linking needs. That means we don't really need to play tricks
with search paths to convince the compiler to do linking as we want it.
For system C libraries, the convention has been anyway to place static and
dynamic libs next to each other, so we need to deal with that issue
anyway and it is outside of our control. But this is out of the scope
of this patch.
This patch is backwards compatible with cabal. Cabal should however
be patched to use the new '-fully-static' switch.
- - - - -
ad3c808d by Julian Ospald at 2026-01-09T02:48:53-05:00
Warn when "-dynamic" is mixed with "-staticlib"
- - - - -
322dd672 by Matthew Pickering at 2026-01-09T02:49:35-05:00
rts: Use INFO_TABLE_CONSTR for stg_dummy_ret_closure
Since the closure type is CONSTR_NOCAF, we need to use INFO_TABLE_CONSTR
to populate the constructor description field (this crashes ghc-debug
when decoding AP_STACK frames sometimes)
Fixes #26745
- - - - -
039bac4c by Ben Gamari at 2026-01-09T20:22:16-05:00
ghc-internal: Move STM utilities out of GHC.Internal.Conc.Sync
This is necessary to avoid an import cycle on Windows when importing
`GHC.Internal.Exception.Context` in `GHC.Internal.Conc.Sync`.
On the road to address #25365.
- - - - -
8c389e8c by Ben Gamari at 2026-01-09T20:22:16-05:00
base: Capture backtrace from throwSTM
Implements core-libraries-committee#297.
Fixes #25365.
- - - - -
e1ce1fc3 by Ben Gamari at 2026-01-09T20:22:16-05:00
base: Annotate rethrown exceptions in catchSTM with WhileHandling
Implements core-libraries-committee#298
- - - - -
c4ebdbdf by Cheng Shao at 2026-01-09T20:23:06-05:00
compiler: make getPrim eagerly evaluate its result
This commit makes `GHC.Utils.Binary.getPrim` eagerly evaluate its
result, to avoid accidental laziness when future patches build other
binary parsers using `getPrim`.
- - - - -
66a0c4f7 by Cheng Shao at 2026-01-09T20:23:06-05:00
compiler: implement fast get/put for Word16/Word32/Word64
Previously, `GHC.Utils.Binary` contains `get`/`put` functions for
`Word16`/`Word32`/`Word64` which always loads and stores them as
big-endian words at a potentially unaligned address. The previous
implementation is based on loads/stores of individual bytes and
concatenating bytes with bitwise operations, which currently cannot be
fused to a single load/store operation by GHC.
This patch implements fast `get`/`put` functions for
`Word16`/`Word32`/`Word64` based on a single memory load/store, with
an additional `byteSwap` operation on little-endian hosts. It is based
on unaligned load/store primops added since GHC 9.10, and we already
require booting with at least 9.10, so it's about time to switch to
this faster path.
- - - - -
641ec3f0 by Simon Peyton Jones at 2026-01-09T20:23:55-05:00
Fix scoping errors in specialisation
Using -fspecialise-aggressively in #26682 showed up a couple of
subtle errors in the type-class specialiser.
* dumpBindUDs failed to call `deleteCallsMentioning`, resulting in a
call that mentioned a dictionary that was not in scope. This call
has been missing since 2009!
commit c43c981705ec33da92a9ce91eb90f2ecf00be9fe
Author: Simon Peyton Jones <simonpj(a)microsoft.com>
Date: Fri Oct 23 16:15:51 2009 +0000
Fixed by re-combining `dumpBindUDs` and `dumpUDs`.
* I think there was another bug involving the quantified type
variables in polymorphic specialisation. In any case I refactored
`specHeader` and `spec_call` so that the former looks for the
extra quantified type variables rather than the latter. This
is quite a worthwhile simplification: less code, easier to grok.
Test case in simplCore/should_compile/T26682,
brilliantly minimised by @sheaf.
- - - - -
2433e91d by Cheng Shao at 2026-01-09T20:24:43-05:00
compiler: change sectionProtection to take SectionType argument
This commit changes `sectionProtection` to only take `SectionType`
argument instead of whole `Section`, since it doesn't need the Cmm
section content anyway, and it can then be called in parts of NCG
where we only have a `SectionType` in scope.
- - - - -
e5926fbe by Cheng Shao at 2026-01-09T20:24:43-05:00
compiler: change isInitOrFiniSection to take SectionType argument
This commit changes `isInitOrFiniSection` to only take `SectionType`
argument instead of whole `Section`, since it doesn't need the Cmm
section content anyway, and it can then be called in parts of NCG
where we only have a `SectionType` in scope. Also marks it as
exported.
- - - - -
244d57d7 by Cheng Shao at 2026-01-09T20:24:43-05:00
compiler: fix split sections on windows
This patch fixes split sections on windows by emitting the right
COMDAT section header in NCG, see added comment for more explanation.
Fix #26696 #26494.
-------------------------
Metric Decrease:
LargeRecord
T9675
size_hello_artifact
size_hello_artifact_gzip
size_hello_unicode
size_hello_unicode_gzip
Metric Increase:
T13035
-------------------------
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
182f3d0f by Cheng Shao at 2026-01-09T20:25:28-05:00
iserv: add comment about -fkeep-cafs
- - - - -
49675b69 by Matthew Craven at 2026-01-09T20:26:14-05:00
Account for "stupid theta" in demand sig for DataCon wrappers
Fixes #26748.
- - - - -
f3c18890 by Samuel Thibault at 2026-01-10T15:48:22+01:00
hurd: Fix getExecutablePath build
3939a8bf93e27 ("GNU/Hurd: Add getExecutablePath support") added using
/proc/self/exe for GNU/Hurd but missed adding the required imports for
the corresponding code.
- - - - -
7f15bd15 by Samuel Thibault at 2026-01-12T07:16:25-05:00
Fix the OS string encoding for GNU/Hurd
Following https://github.com/haskell/cabal/pull/9434/files , and as seen
in the various gnu_HOST_OS usages in the source code, it is expected that
GNU/Hurd is advertised as "gnu", like the autotools do.
- - - - -
1db2f240 by Andrew Lelechenko at 2026-01-12T07:17:06-05:00
Add since annotation for Data.Bifoldable1
Fixes #26432
- - - - -
e038a383 by Sven Tennie at 2026-01-12T07:17:49-05:00
Ignore Windows CI tool directories in Git
Otherwise, we see thousands of changes in `git status` which is very
confusing to work with.
- - - - -
023c301c by sheaf at 2026-01-13T04:57:30-05:00
Don't re-use stack slots for growing registers
This commit avoids re-using a stack slot for a register that has grown
but already had a stack slot.
For example, suppose we have stack slot assigments
%v1 :: FF64 |-> StackSlot 0
%v2 :: FF64 |-> StackSlot 1
Later, we start using %v1 at a larger format (e.g. F64x2) and we need
to spill it again. Then we **must not** use StackSlot 0, as a spill
at format F64x2 would clobber the data in StackSlot 1.
This can cause some fragmentation of the `StackMap`, but that's probably
OK.
Fixes #26668
- - - - -
d0966e64 by fendor at 2026-01-13T04:58:11-05:00
Remove `traceId` from ghc-pkg executable
- - - - -
20d7efec by Simon Peyton Jones at 2026-01-13T12:41:22-05:00
Make SpecContr rules fire a bit later
See #26615 and Note [SpecConstr rule activation]
- - - - -
8bc4eb8c by Andrew Lelechenko at 2026-01-13T12:42:03-05:00
Upgrade mtl submodule to 2.3.2
Fixes #26656
- - - - -
c94aaacd by Cheng Shao at 2026-01-13T12:42:44-05:00
compiler: remove iserv and only use on-demand external interpreter
This patch removes `iserv` from the tree completely. Hadrian would no
longer build or distribute `iserv`, and the GHC driver would use the
on-demand external interpreter by default when invoked with
`-fexternal-interpreter`, without needing to specify `-pgmi ""`. This
has multiple benefits:
- It allows cleanup of a lot of legacy hacks in the hadrian codebase.
- It paves the way for running cross ghc's iserv via cross emulator
(#25523), fixing TH/ghci support for cross targets other than
wasm/js.
- - - - -
c1fe0097 by Peter Trommler at 2026-01-14T03:54:49-05:00
PPC NCG: Fix shift right MO code
The shift amount in shift right [arithmetic] MOs is machine word
width. Therefore remove unnecessary zero- or sign-extending of
shift amount.
It looks harmless to extend the shift amount argument because the
shift right instruction uses only the seven lowest bits (i. e. mod 128).
But now we have a conversion operation from a smaller type to word width
around a memory load at word width. The types are not matching up but
there is no check done in CodeGen. The necessary conversion from word
width down to the smaller width would be translated into a no-op on
PowerPC anyway. So all seems harmless if it was not for a small
optimisation in getRegister'.
In getRegister' a load instruction with the smaller width of the
conversion operation was generated. This loaded the most significant
bits of the word in memory on a big-endian platform. These bits were
zero and hence shift right was used with shift amount zero and not one
as required in test Sized.
Fixes #26519
- - - - -
2dafc65a by Cheng Shao at 2026-01-14T03:55:31-05:00
Tree-wide cleanup of cygwin logic
GHC has not supported cygwin for quite a few years already, and will
not resume support in the forseeable future. The only supported
windows toolchain is clang64/clangarm64 of the msys2 project. This
patch cleans up the unused cygwin logic in the tree.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
66b96e2a by Teo Camarasu at 2026-01-14T03:56:13-05:00
Set default eventlog-flush-interval to 5s
Resolves #26707
- - - - -
d0254579 by Andrew Lelechenko at 2026-01-14T03:56:53-05:00
Document when -maxN RTS option was added
- - - - -
f25e2b12 by Cheng Shao at 2026-01-14T11:10:39-05:00
testsuite: remove obsolete --ci option from the testsuite driver
This patch removes the obsolete `--ci` option from the testsuite
driver: neither the CI scripts nor hadrian ever invokes the testsuite
driver with `--ci`, and the perf notes are always fetched to the
`refs/notes/perf` local reference anyway.
- - - - -
7964763b by Julian Ospald at 2026-01-14T11:11:31-05:00
Fix fetch_cabal
* download cabal if the existing one is of an older version
* fix FreeBSD download url
* fix unpacking on FreeBSD
- - - - -
6b0129c1 by Julian Ospald at 2026-01-14T11:11:31-05:00
Bump toolchain in CI
- - - - -
0f53ccc6 by Julian Ospald at 2026-01-14T11:11:31-05:00
Use libffi-clib
Previously, we would build libffi via hadrian
and bundle it manually with the GHC bindist.
This now moves all that logic out of hadrian
and allows us to have a clean Haskell package
to build and link against and ship it without
extra logic.
This patch still retains the ability to link
against a system libffi.
The main reason of bundling libffi was that on
some platforms (e.g. FreeBSD and Mac), system libffi
is not visible to the C toolchain by default,
so users would require settings in e.g. cabal
to be able to compile anything.
This adds the submodule libffi-clib to the repository.
- - - - -
5e1cd595 by Peng Fan at 2026-01-14T11:12:26-05:00
NCG/LA64: add support for la664 micro architecture
Add '-mla664' flag to LA664, which has some new features:
atomic instructions, dbar hints, etc.
'LA464' is the default so that unrecognized instructions are not
generated.
- - - - -
15945537 by Simon Peyton Jones at 2026-01-16T11:00:26+00:00
Work in progress on unfoldings re-engineering
- - - - -
1dd991c2 by Simon Peyton Jones at 2026-01-16T11:00:26+00:00
Fix a bad, subtle bug in exprIsConApp_maybe
In extend_in_scope We were simply overwriting useful bindings in the
in-scope set, notably ones that had unfoldings. That could lead to
repeated simplifier iterations.
- - - - -
f3b0e076 by Simon Peyton Jones at 2026-01-16T11:00:27+00:00
Minor refactoring...
Plus: don't be so eager to inline when argument is a non-value,
but has some struture.
We want *some* incentive though.
- - - - -
f12e2670 by Simon Peyton Jones at 2026-01-16T11:00:27+00:00
Adjust
* Reduce caseElimDiscount to 10
Example: f_nand in spectral/hartel/event is quite big but was still
getting inlined; that make f_simulate too big for SpecConstr
* Increase jumpSize. Not so much cheaper than tail calls.
I'm trying making them the same size.
- - - - -
a4a3469b by Simon Peyton Jones at 2026-01-16T11:00:27+00:00
Typo
- - - - -
4a430d22 by Simon Peyton Jones at 2026-01-16T11:00:27+00:00
Wibbles
- - - - -
e31a0ede by Simon Peyton Jones at 2026-01-16T11:00:27+00:00
Wibble unused variables
- - - - -
2b895e83 by Simon Peyton Jones at 2026-01-16T11:00:27+00:00
Make case expressions and applications a bit bigger
- - - - -
440f2511 by Simon Peyton Jones at 2026-01-16T11:00:27+00:00
Wibbles
- - - - -
315 changed files:
- .gitignore
- .gitlab/ci.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- .gitmodules
- CODEOWNERS
- cabal.project-reinstall
- compiler/GHC.hs
- compiler/GHC/Builtin/PrimOps.hs
- compiler/GHC/Cmm.hs
- compiler/GHC/Cmm/Info.hs
- compiler/GHC/Cmm/InitFini.hs
- compiler/GHC/Cmm/Utils.hs
- compiler/GHC/CmmToAsm/AArch64/Ppr.hs
- compiler/GHC/CmmToAsm/Config.hs
- compiler/GHC/CmmToAsm/PPC/CodeGen.hs
- compiler/GHC/CmmToAsm/Ppr.hs
- compiler/GHC/CmmToAsm/Reg/Linear.hs
- compiler/GHC/CmmToAsm/Reg/Linear/StackMap.hs
- compiler/GHC/CmmToAsm/Wasm/FromCmm.hs
- compiler/GHC/CmmToAsm/X86/Ppr.hs
- compiler/GHC/CmmToC.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/CmmToLlvm/Data.hs
- compiler/GHC/Core.hs
- compiler/GHC/Core/FamInstEnv.hs
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/LiberateCase.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Env.hs
- compiler/GHC/Core/Opt/Simplify/Inline.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Opt/Specialise.hs
- compiler/GHC/Core/Opt/WorkWrap.hs
- compiler/GHC/Core/Ppr.hs
- compiler/GHC/Core/Rules.hs
- compiler/GHC/Core/Seq.hs
- compiler/GHC/Core/SimpleOpt.hs
- compiler/GHC/Core/Subst.hs
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/TyCon.hs
- compiler/GHC/Core/Unfold.hs
- compiler/GHC/Core/Unfold/Make.hs
- compiler/GHC/Core/Unify.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/CmmToAsm.hs
- compiler/GHC/Driver/Config/Core/Opt/Simplify.hs
- compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/MakeFile.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Linker/Dynamic.hs
- compiler/GHC/Linker/Executable.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Unit.hs
- compiler/GHC/Runtime/Interpreter/C.hs
- compiler/GHC/Runtime/Interpreter/Init.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- compiler/GHC/StgToJS/Linker/Utils.hs
- compiler/GHC/SysTools/Terminal.hs
- compiler/GHC/Tc/Errors.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/Splice.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Default.hs
- compiler/GHC/Tc/Solver/Dict.hs
- compiler/GHC/Tc/Solver/Equality.hs
- compiler/GHC/Tc/Solver/FunDeps.hs
- compiler/GHC/Tc/Solver/InertSet.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/Solver/Rewrite.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/CtLoc.hs
- compiler/GHC/Tc/Utils/Monad.hs
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Types/Id.hs
- compiler/GHC/Types/Id/Make.hs
- compiler/GHC/Types/TyThing.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/State.hs
- compiler/GHC/Utils/Binary.hs
- configure.ac
- distrib/configure.ac.in
- − docs/Makefile
- − docs/storage-mgt/Makefile
- docs/users_guide/9.16.1-notes.rst
- − docs/users_guide/Makefile
- docs/users_guide/exts/pragmas.rst
- docs/users_guide/exts/table.rst
- docs/users_guide/ghci.rst
- docs/users_guide/packages.rst
- docs/users_guide/phases.rst
- docs/users_guide/using-concurrent.rst
- docs/users_guide/using.rst
- docs/users_guide/win32-dlls.rst
- − driver/Makefile
- − driver/ghc/Makefile
- − driver/ghci/Makefile
- driver/ghci/ghci.c
- − driver/haddock/Makefile
- driver/utils/cwrapper.c
- driver/utils/isMinTTY.c
- − driver/utils/merge_sections.ld
- − driver/utils/merge_sections_pe.ld
- ghc/Main.hs
- − ghc/Makefile
- hadrian/bindist/cwrappers/cwrapper.c
- hadrian/cfg/default.host.target.in
- hadrian/cfg/default.target.in
- hadrian/doc/flavours.md
- hadrian/doc/user-settings.md
- hadrian/hadrian.cabal
- hadrian/src/Base.hs
- hadrian/src/Builder.hs
- hadrian/src/Context.hs
- hadrian/src/Flavour.hs
- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Hadrian/Haskell/Hash.hs
- hadrian/src/Oracles/Flag.hs
- hadrian/src/Oracles/Setting.hs
- hadrian/src/Packages.hs
- hadrian/src/Rules.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/CabalReinstall.hs
- hadrian/src/Rules/Documentation.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Gmp.hs
- − hadrian/src/Rules/Libffi.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Program.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Rules/SourceDist.hs
- hadrian/src/Rules/Test.hs
- hadrian/src/Settings/Builders/Cabal.hs
- hadrian/src/Settings/Builders/Ghc.hs
- hadrian/src/Settings/Builders/Hsc2Hs.hs
- − hadrian/src/Settings/Builders/MergeObjects.hs
- hadrian/src/Settings/Builders/SplitSections.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Flavours/Validate.hs
- hadrian/src/Settings/Packages.hs
- hadrian/src/Settings/Program.hs
- − libffi-tarballs
- − libraries/Makefile
- libraries/base/changelog.md
- libraries/base/src/Data/Bifoldable1.hs
- libraries/base/src/GHC/Conc.hs
- libraries/base/src/GHC/Conc/Sync.hs
- libraries/base/tests/IO/T12010/cbits/initWinSock.c
- − libraries/doc/Makefile
- libraries/ghc-boot/GHC/Unit/Database.hs
- libraries/ghc-internal/cbits/consUtils.c
- libraries/ghc-internal/configure.ac
- libraries/ghc-internal/ghc-internal.buildinfo.in
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/include/HsIntegerGmp.h.in
- libraries/ghc-internal/src/GHC/Internal/Conc/IO.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/POSIX.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs
- libraries/ghc-internal/src/GHC/Internal/Conc/Sync.hs-boot
- libraries/ghc-internal/src/GHC/Internal/Conc/Windows.hs
- libraries/ghc-internal/src/GHC/Internal/ConsoleHandler.hsc
- libraries/ghc-internal/src/GHC/Internal/Control/Monad.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Event/Windows/Thread.hs
- libraries/ghc-internal/src/GHC/Internal/Exception/Context.hs
- libraries/ghc-internal/src/GHC/Internal/IO/Handle.hs
- + libraries/ghc-internal/src/GHC/Internal/STM.hs
- libraries/ghc-internal/src/GHC/Internal/System/Environment/ExecutablePath.hsc
- libraries/ghc-platform/src/GHC/Platform/ArchOS.hs
- + libraries/libffi-clib
- libraries/mtl
- linters/lint-codes/LintCodes/Static.hs
- − linters/lint-codes/Makefile
- − linters/lint-notes/Makefile
- llvm-passes
- + m4/fp_linker_supports_verbatim.m4
- m4/ghc_select_file_extensions.m4
- m4/prep_target_file.m4
- mk/system-cxx-std-lib-1.0.conf.in
- packages
- − rts/Makefile
- rts/RtsFlags.c
- rts/StgMiscClosures.cmm
- rts/configure.ac
- − rts/include/Makefile
- rts/include/rts/ghc_ffi.h
- rts/rts.buildinfo.in
- rts/rts.cabal
- + testsuite/driver/_elffile.py
- testsuite/driver/perf_notes.py
- testsuite/driver/runtests.py
- testsuite/driver/testglobals.py
- testsuite/driver/testlib.py
- testsuite/ghc-config/ghc-config.hs
- testsuite/mk/test.mk
- + testsuite/tests/dmdanal/should_run/T26748.hs
- + testsuite/tests/dmdanal/should_run/T26748.stdout
- testsuite/tests/dmdanal/should_run/all.T
- − testsuite/tests/driver/T24731.hs
- testsuite/tests/driver/all.T
- + testsuite/tests/driver/fully-static/Hello.hs
- + testsuite/tests/driver/fully-static/Makefile
- + testsuite/tests/driver/fully-static/all.T
- + testsuite/tests/driver/fully-static/fully-static.stdout
- + testsuite/tests/driver/fully-static/test/Test.hs
- + testsuite/tests/driver/fully-static/test/test.pkg
- + testsuite/tests/driver/mostly-static/Hello.hs
- + testsuite/tests/driver/mostly-static/Makefile
- + testsuite/tests/driver/mostly-static/all.T
- + testsuite/tests/driver/mostly-static/mostly-static.stdout
- + testsuite/tests/driver/mostly-static/test/test.c
- + testsuite/tests/driver/mostly-static/test/test.h
- + testsuite/tests/driver/mostly-static/test/test.pkg
- + testsuite/tests/driver/recomp26183/M.hs
- + testsuite/tests/driver/recomp26183/M2A.hs
- + testsuite/tests/driver/recomp26183/M2B.hs
- + testsuite/tests/driver/recomp26183/Makefile
- + testsuite/tests/driver/recomp26183/all.T
- + testsuite/tests/driver/recomp26183/recomp26183.stderr
- + testsuite/tests/driver/recomp26705/M.hs
- + testsuite/tests/driver/recomp26705/M2A.hs
- + testsuite/tests/driver/recomp26705/M2B.hs
- + testsuite/tests/driver/recomp26705/Makefile
- + testsuite/tests/driver/recomp26705/all.T
- + testsuite/tests/driver/recomp26705/recomp26705.stderr
- testsuite/tests/indexed-types/should_compile/CEqCanOccursCheck.hs
- testsuite/tests/indexed-types/should_fail/T12522a.hs
- testsuite/tests/indexed-types/should_fail/T26176.stderr
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- testsuite/tests/numeric/should_run/all.T
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail10.stderr
- testsuite/tests/parser/should_fail/RecordDotSyntaxFail13.stderr
- testsuite/tests/parser/should_fail/T20654a.stderr
- testsuite/tests/pmcheck/should_compile/T15753c.hs
- + testsuite/tests/pmcheck/should_compile/T15753c.stderr
- testsuite/tests/pmcheck/should_compile/T15753d.hs
- + testsuite/tests/pmcheck/should_compile/T15753d.stderr
- + testsuite/tests/pmcheck/should_compile/T22652.hs
- + testsuite/tests/pmcheck/should_compile/T22652a.hs
- + testsuite/tests/pmcheck/should_compile/T24867.hs
- + testsuite/tests/pmcheck/should_compile/T24867.stderr
- testsuite/tests/pmcheck/should_compile/all.T
- + testsuite/tests/polykinds/T13882.hs
- testsuite/tests/polykinds/all.T
- testsuite/tests/quantified-constraints/T15316A.stderr
- testsuite/tests/quantified-constraints/T17267.stderr
- testsuite/tests/quantified-constraints/T17267a.stderr
- testsuite/tests/quantified-constraints/T17267b.stderr
- testsuite/tests/quantified-constraints/T17267c.stderr
- testsuite/tests/quantified-constraints/T17267e.stderr
- testsuite/tests/quantified-constraints/T17458.stderr
- testsuite/tests/rts/linker/rdynamic.hs
- testsuite/tests/simplCore/should_compile/T14003.stderr
- testsuite/tests/simplCore/should_compile/T19672.stderr
- testsuite/tests/simplCore/should_compile/T21763.stderr
- testsuite/tests/simplCore/should_compile/T21763a.stderr
- + testsuite/tests/simplCore/should_compile/T26615.hs
- + testsuite/tests/simplCore/should_compile/T26615.stderr
- + testsuite/tests/simplCore/should_compile/T26615a.hs
- + testsuite/tests/simplCore/should_compile/T26681.hs
- + testsuite/tests/simplCore/should_compile/T26682.hs
- + testsuite/tests/simplCore/should_compile/T26682a.hs
- + testsuite/tests/simplCore/should_compile/T26709.hs
- + testsuite/tests/simplCore/should_compile/T26709.stderr
- testsuite/tests/simplCore/should_compile/T4908.stderr
- testsuite/tests/simplCore/should_compile/all.T
- testsuite/tests/simplCore/should_compile/spec-inline.stderr
- testsuite/tests/typecheck/should_compile/T16188.hs
- testsuite/tests/typecheck/should_fail/ContextStack1.stderr
- testsuite/tests/typecheck/should_fail/FD3.stderr
- testsuite/tests/typecheck/should_fail/FDsFromGivens2.stderr
- testsuite/tests/typecheck/should_fail/FunDepOrigin1b.stderr
- testsuite/tests/typecheck/should_fail/T13506.stderr
- testsuite/tests/typecheck/should_fail/T15767.stderr
- testsuite/tests/typecheck/should_fail/T19415.stderr
- testsuite/tests/typecheck/should_fail/T19415b.stderr
- testsuite/tests/typecheck/should_fail/T22924b.stderr
- + testsuite/tests/typecheck/should_fail/T23162b.hs
- + testsuite/tests/typecheck/should_fail/T23162b.stderr
- + testsuite/tests/typecheck/should_fail/T23162c.hs
- + testsuite/tests/typecheck/should_fail/T23162d.hs
- testsuite/tests/typecheck/should_fail/T25325.stderr
- testsuite/tests/typecheck/should_fail/T5236.stderr
- testsuite/tests/typecheck/should_fail/T5246.stderr
- testsuite/tests/typecheck/should_fail/T5978.stderr
- testsuite/tests/typecheck/should_fail/T9612.stderr
- testsuite/tests/typecheck/should_fail/TcCoercibleFail.stderr
- testsuite/tests/typecheck/should_fail/all.T
- testsuite/tests/typecheck/should_fail/tcfail143.stderr
- utils/deriveConstants/Main.hs
- utils/ghc-pkg/Main.hs
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Link.hs
- utils/haddock/haddock-api/src/Haddock/Convert.hs
- − utils/iserv/cbits/iservmain.c
- − utils/iserv/iserv.cabal.in
- − utils/iserv/src/Main.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/41f2321f344a8da748e0c75d26bdda…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/41f2321f344a8da748e0c75d26bdda…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
16 Jan '26
Andreas Klebinger pushed to branch wip/andreask/bomb_out at Glasgow Haskell Compiler / GHC
Commits:
6119e78c by Andreas Klebinger at 2026-01-16T11:27:50+01:00
Fix some warnings
- - - - -
1 changed file:
- compiler/GHC/Core/Unfold.hs
Changes:
=====================================
compiler/GHC/Core/Unfold.hs
=====================================
@@ -1094,9 +1094,6 @@ In a function application (f a b)
Code for manipulating sizes
-}
--- | Does an ExprSize include an evaluation Discount?
-data HasDiscount = NoDiscount | WithDiscount deriving (Eq)
-
type PlainSize = Int -- Things that have a size, but not argument discount, nor scrut discount
-- | The size of a candidate expression for unfolding
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6119e78c154526c69e1ceaa1670816e…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/6119e78c154526c69e1ceaa1670816e…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/T24464] Start at moving static forms straight to top level
by Simon Peyton Jones (@simonpj) 16 Jan '26
by Simon Peyton Jones (@simonpj) 16 Jan '26
16 Jan '26
Simon Peyton Jones pushed to branch wip/T24464 at Glasgow Haskell Compiler / GHC
Commits:
5aac338c by Simon Peyton Jones at 2026-01-16T10:26:11+00:00
Start at moving static forms straight to top level
Just for CI. Needs documentation.
Making static bindings have static constraint solving
- - - - -
44 changed files:
- compiler/GHC/Core/Lint.hs
- compiler/GHC/Core/Opt/Pipeline.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Driver/Config/Core/Lint.hs
- compiler/GHC/Hs/Binds.hs
- compiler/GHC/Hs/Decls.hs
- compiler/GHC/Hs/Expr.hs
- compiler/GHC/Hs/Instances.hs
- compiler/GHC/Hs/Syn/Type.hs
- compiler/GHC/Hs/Utils.hs
- compiler/GHC/HsToCore.hs
- compiler/GHC/HsToCore/Docs.hs
- compiler/GHC/HsToCore/Expr.hs
- compiler/GHC/HsToCore/Monad.hs
- compiler/GHC/HsToCore/Pmc/Desugar.hs
- compiler/GHC/HsToCore/Quote.hs
- compiler/GHC/HsToCore/Ticks.hs
- compiler/GHC/HsToCore/Types.hs
- compiler/GHC/Iface/Ext/Ast.hs
- compiler/GHC/Iface/Tidy/StaticPtrTable.hs
- compiler/GHC/Rename/Bind.hs
- compiler/GHC/Rename/Expr.hs
- compiler/GHC/Rename/Module.hs
- compiler/GHC/Tc/Deriv.hs
- compiler/GHC/Tc/Errors/Ppr.hs
- compiler/GHC/Tc/Errors/Types.hs
- compiler/GHC/Tc/Gen/Bind.hs
- compiler/GHC/Tc/Gen/Expr.hs
- compiler/GHC/Tc/Gen/Head.hs
- compiler/GHC/Tc/Gen/Pat.hs
- compiler/GHC/Tc/Module.hs
- compiler/GHC/Tc/Solver.hs
- compiler/GHC/Tc/Solver/Monad.hs
- compiler/GHC/Tc/TyCl/Instance.hs
- compiler/GHC/Tc/TyCl/Utils.hs
- compiler/GHC/Tc/Types.hs
- compiler/GHC/Tc/Types/BasicTypes.hs
- compiler/GHC/Tc/Types/Constraint.hs
- compiler/GHC/Tc/Types/Origin.hs
- compiler/GHC/Tc/Utils/Env.hs
- − compiler/GHC/Tc/Utils/TcMType.hs-boot
- compiler/GHC/Tc/Utils/Unify.hs
- compiler/GHC/Tc/Zonk/TcType.hs
- compiler/GHC/Tc/Zonk/Type.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5aac338c400877000a18bf6934ba053…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/5aac338c400877000a18bf6934ba053…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/romes/hadrian-cross-stage2-rebase_SVEN_FINAL] 41 commits: ghc-internal: remove unused GMP macros
by Sven Tennie (@supersven) 16 Jan '26
by Sven Tennie (@supersven) 16 Jan '26
16 Jan '26
Sven Tennie pushed to branch wip/romes/hadrian-cross-stage2-rebase_SVEN_FINAL at Glasgow Haskell Compiler / GHC
Commits:
a20542d2 by Cheng Shao at 2026-01-06T19:38:38-05:00
ghc-internal: remove unused GMP macros
This patch removes unused GMP related macros from `ghc-internal`. The
in-tree GMP version was hard coded and outdated, but it was not used
anywhere anyway.
- - - - -
4079dcd6 by Cheng Shao at 2026-01-06T19:38:38-05:00
hadrian: fix in-tree gmp configure error on newer c compilers
Building in-tree gmp on newer c compilers that default to c23 fails at
configure stage, this patch fixes it, see added comment for
explanation.
- - - - -
414d1fe1 by Cheng Shao at 2026-01-06T19:39:20-05:00
compiler: fix LLVM backend pdep/pext handling for i386 target
This patch fixes LLVM backend's pdep/pext handling for i386 target,
and also removes non-existent 128/256/512 bit hs_pdep/hs_pext callees.
See amended note for more explanation. Fixes #26450.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
c7f6fba3 by Cheng Shao at 2026-01-06T19:39:20-05:00
ci: remove allow_failure flag for i386 alpine job
The LLVM codegen issue for i386 has been fixed, and the i386 alpine
job should pass now. This commit removes the allow_failure flag so
that other i386 regressions in the future are signaled more timely.
- - - - -
52d00c05 by Simon Peyton Jones at 2026-01-07T10:24:21-05:00
Add missing InVar->OutVar lookup in SetLevels
As #26681 showed, the SetLevels pass was failing to map an InVar to
an OutVar. Very silly! I'm amazed it hasn't broken before now.
I have improved the type singatures (to mention InVar and OutVar)
so it's more obvious what needs to happen.
- - - - -
ab0a5594 by Cheng Shao at 2026-01-07T10:25:04-05:00
hadrian: drop deprecated pkgHashSplitObjs code path
This patch drops deprecated `pkgHashSplitObjs` code path from hadrian,
since GHC itself has removed split objs support many versions ago and
this code path is unused.
- - - - -
bb3a2ba1 by Cheng Shao at 2026-01-07T10:25:44-05:00
hadrian: remove linting/assertion in quick-validate flavour
The `quick-validate` flavour is meant for testing ghc and passing the
testsuite locally with similar settings to `validate` but faster. This
patch removes the linting/assertion overhead in `quick-validate` to
improve developer experience. I also took the chance to simplify
redundant logic of rts/library way definition in `validate` flavour.
- - - - -
7971f5dd by Cheng Shao at 2026-01-07T10:26:26-05:00
deriveConstants: clean up unused constants
This patch cleans up unused constants from `deriveConstants`, they are
not used by C/Cmm code in the RTS, nor compiler-generated code.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
4df96993 by Cheng Shao at 2026-01-07T10:27:08-05:00
hadrian: pass -fno-omit-frame-pointer with +debug_info
This patch adds `-fno-omit-frame-pointer` as C/C++ compilation flag
when compiling with `+debug_info` flavour transformer. It's a sane
default when you care about debugging and reliable backtraces, and
makes debugging/profiling with bpf easier.
- - - - -
8a3900a3 by Aaron Allen at 2026-01-07T10:27:57-05:00
[26705] Include TyCl instances in data fam iface entry
Ensures dependent modules are recompiled when the class instances for a
data family instance change.
resolves #26705
- - - - -
a0b980af by Cheng Shao at 2026-01-07T10:28:38-05:00
hadrian: remove unused Hp2Ps/Hpc builders
This patch removes the Hp2Ps/Hpc builders from hadrian, they are
unused in the build system. Note that the hp2ps/hpc programs are still
built and not affected.
- - - - -
50a58757 by Cheng Shao at 2026-01-07T10:29:20-05:00
hadrian: only install js files to libdir for wasm/js targets
There are certain js files required for wasm/js targets to work, and
previously hadrian would install those js files to libdir
unconditionally on other targets as well. This could be a minor
annoyance for packagers especially when the unused js files contain
shebangs that interfere with the packaging process. This patch makes
hadrian only selectively install the right js files for the right
targets.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
da40e553 by Simon Peyton Jones at 2026-01-07T10:30:00-05:00
Add flavour transformer assertions_stage1
This allows us to enable -DDEBUG assertions in the stage1 compiler
- - - - -
ec3cf767 by Cheng Shao at 2026-01-08T06:24:31-05:00
make: remove unused Makefiles from legacy make build system
This patch removes unused Makefiles from legacy make build system; now
they are never used by hadrian in any way, and they already include
common boilerplate mk files that are long gone in the make build
system removal, hence the housecleaning.
Co-authored-by: Codex <codex(a)openai.com>
- - - - -
04ea3f83 by Cheng Shao at 2026-01-08T06:25:13-05:00
compiler: use -O3 as LLVM optimization level for ghc -O2
The GHC driver clamps LLVM optimization level to `-O2` due to LLVM
crashes, but those were historical issues many years ago that are no
longer relevant for LLVM versions we support today. This patch changes
the driver to use `-O3` as LLVM optimization level when compiling with
`-O2`, which is a better default when we're willing to trade
compilation time for faster generated code.
- - - - -
472df471 by Peter Trommler at 2026-01-08T13:28:54-05:00
Use half-word literals in info tables
With this commit info tables are mapped to the same assembler code
on big-endian and little-endian platforms.
Fixes #26579.
- - - - -
393f9c51 by Simon Peyton Jones at 2026-01-08T13:29:35-05:00
Refactor srutOkForBinderSwap
This MR does a small refactor:
* Moves `scrutOkForBinderSwap` and `BinderSwapDecision`
to GHC.Core.Utils
* Inverts the sense of the coercion it returns, which makes
more sense
No effect on behaviour
- - - - -
ad76fb0f by Simon Peyton Jones at 2026-01-08T13:29:36-05:00
Improve case merging
This small MR makes case merging happen a bit more often than
it otherwise could, by getting join points out of the way.
See #26709 and GHC.Core.Utils
Note [Floating join points out of DEFAULT alternatives]
- - - - -
4c9395f5 by Cheng Shao at 2026-01-08T13:30:16-05:00
hadrian: remove broken hsc2hs flag when cross compiling to windows
This patch removes the `--via-asm` hsc2hs flag when cross compiling to
windows. With recent llvm-mingw toolchain, it would fail with:
```
x86_64-w64-mingw32-hsc2hs: Cannot combine instructions: [Quad 8,Long 4,Long 241,Ref ".Ltmp1-.Ltmp0"]
```
The hsc2hs default `--cross-compile` logic is slower but works.
- - - - -
71fdef55 by Simon Peyton Jones at 2026-01-08T13:30:57-05:00
Try harder to keep the substitution empty
Avoid unnecessary cloning of variables in the Simplifier.
Addresses #26724,
See Note [Keeping the substitution empty]
We get some big wins in compile time
Metrics: compile_time/bytes allocated
-------------------------------------
Baseline
Test Metric value New value Change
----------------------------------------------------------------------------
CoOpt_Singletons(normal) ghc/alloc 721,544,088 692,174,216 -4.1% GOOD
LargeRecord(normal) ghc/alloc 1,268,031,157 1,265,168,448 -0.2%
T14766(normal) ghc/alloc 918,218,533 688,432,296 -25.0% GOOD
T15703(normal) ghc/alloc 318,103,629 306,638,016 -3.6% GOOD
T17836(normal) ghc/alloc 419,174,584 418,400,824 -0.2%
T18478(normal) ghc/alloc 471,042,976 470,261,376 -0.2%
T20261(normal) ghc/alloc 573,387,162 563,663,336 -1.7%
T24984(normal) ghc/alloc 87,832,666 87,636,168 -0.2%
T25196(optasm) ghc/alloc 1,103,284,040 1,101,376,992 -0.2%
hard_hole_fits(normal) ghc/alloc 224,981,413 224,608,208 -0.2%
geo. mean -0.3%
minimum -25.0%
maximum +0.1%
Metric Decrease:
CoOpt_Singletons
T14766
T15703
- - - - -
30341168 by Simon Peyton Jones at 2026-01-08T13:31:38-05:00
Add regression test for #24867
- - - - -
1ac1a541 by Julian Ospald at 2026-01-09T02:48:53-05:00
Support statically linking executables properly
Fixes #26434
In detail, this does a number of things:
* Makes GHC aware of 'extra-libraries-static' (this changes the package
database format).
* Adds a switch '-static-external' that will honour 'extra-libraries-static'
to link external system dependencies statically.
* Adds a new field to settings/targets: "ld supports verbatim namespace".
This field is used by '-static-external' to conditionally use '-l:foo.a'
syntax during linking, which is more robust than trying to find the
absolute path to an archive on our own.
* Adds a switch '-fully-static' that is meant as a high-level interface
for e.g. cabal. This also honours 'extra-libraries-static'.
This also attempts to clean up the confusion around library search directories.
At the moment, we have 3 types of directories in the package database
format:
* library-dirs
* library-dirs-static
* dynamic-library-dirs
However, we only have two types of linking: dynamic or static. Given the
existing logic in 'mungeDynLibFields', this patch assumes that
'library-dirs' is really just nothing but a fallback and always
prefers the more specific variants if they exist and are non-empty.
Conceptually, we should be ok with even just one search dirs variant.
Haskell libraries are named differently depending on whether they're
static or dynamic, so GHC can conveniently pick the right one depending
on the linking needs. That means we don't really need to play tricks
with search paths to convince the compiler to do linking as we want it.
For system C libraries, the convention has been anyway to place static and
dynamic libs next to each other, so we need to deal with that issue
anyway and it is outside of our control. But this is out of the scope
of this patch.
This patch is backwards compatible with cabal. Cabal should however
be patched to use the new '-fully-static' switch.
- - - - -
ad3c808d by Julian Ospald at 2026-01-09T02:48:53-05:00
Warn when "-dynamic" is mixed with "-staticlib"
- - - - -
3c12f79e by Matthew Pickering at 2026-01-16T08:13:56+01:00
Add missing req_interp modifier to T18441fail3 and T18441fail19
These tests require the interpreter but they were failing in a different
way with the javascript backend because the interpreter was disabled and
stderr is ignored by the test.
- - - - -
4b1eeb02 by Matthew Pickering at 2026-01-16T08:13:56+01:00
Use explicit syntax rather than pure
- - - - -
a538c881 by Matthew Pickering at 2026-01-16T08:13:56+01:00
packaging: correctly propagate build/host/target to bindist configure script
At the moment the host and target which we will produce a compiler for
is fixed at the initial configure time. Therefore we need to persist
the choice made at this time into the installation bindist as well so we
look for the right tools, with the right prefixes at install time.
In the future, we want to provide a bit more control about what kind of
bindist we produce so the logic about what the host/target will have to
be written by hadrian rather than persisted by the configure script. In
particular with cross compilers we want to either build a normal stage 2
cross bindist or a stage 3 bindist, which creates a bindist which has a
native compiler for the target platform.
Fixes #21970
- - - - -
f09c7801 by Matthew Pickering at 2026-01-16T08:14:36+01:00
hadrian: Fill in more of the default.host toolchain file
When you are building a cross compiler this file will be used to build
stage1 and it's libraries, so we need enough information here to work
accurately. There is still more work to be done (see for example, word
size is still fixed).
- - - - -
7070c655 by Matthew Pickering at 2026-01-16T08:14:36+01:00
hadrian: Disable docs when cross compiling
Before there were a variety of ad-hoc places where doc building was
disabled when cross compiling.
* Some CI jobs sets --docs=none in gen_ci.hs
* Some CI jobs set --docs=none in .gitlab/ci.sh
* There was some logic in hadrian to not need the ["docs"] target when
making a bindist.
Now the situation is simple:
* If you are cross compiling then defaultDocsTargets is empty by
default.
In theory, there is no reason why we can't build documentation for cross
compiler bindists, but this is left to future work to generalise the
documentation building rules to allow this (#24289)
- - - - -
41da2ff3 by Matthew Pickering at 2026-01-16T08:23:45+01:00
hadrian: Build stage 2 cross compilers
* Most of hadrian is abstracted over the stage in order to remove the
assumption that the target of all stages is the same platform. This
allows the RTS to be built for two different targets for example.
* Abstracts the bindist creation logic to allow building either normal
or cross bindists. Normal bindists use stage 1 libraries and a stage 2
compiler. Cross bindists use stage 2 libararies and a stage 2
compiler.
* hadrian: Make binary-dist-dir the default build target. This allows us
to have the logic in one place about which libraries/stages to build
with cross compilers. Fixes #24192
New hadrian target:
* `binary-dist-dir-cross`: Build a cross compiler bindist (compiler =
stage 1, libraries = stage 2)
This commit also contains various changes to make stage2 compilers
feasible.
-------------------------
Metric Decrease:
ManyAlternatives
MultiComponentModulesRecomp
MultiLayerModulesRecomp
T10421
T12425
T12707
T13035
T13379
T15703
T16577
T18698a
T18698b
T18923
T1969
T21839c
T3294
T4801
T5030
T5321Fun
T5642
T783
T9198
T9872d
T9961
parsing001
T5321FD
T6048
-------------------------
Co-authored-by: Sven Tennie <sven.tennie(a)gmail.com>
- - - - -
63eb994f by Sven Tennie at 2026-01-16T08:23:45+01:00
Align CI scripts with master
Fixup
- - - - -
dd77b17e by Matthew Pickering at 2026-01-16T08:23:45+01:00
ci: Test cross bindists
We remove the special logic for testing in-tree cross
compilers and instead test cross compiler bindists, like we do for all
other platforms.
- - - - -
ebd42dd2 by Matthew Pickering at 2026-01-16T08:23:45+01:00
ci: Introduce CROSS_STAGE variable
In preparation for building and testing stage3 bindists we introduce the
CROSS_STAGE variable which is used by a CI job to determine what kind of
bindist the CI job should produce.
At the moment we are only using CROSS_STAGE=2 but in the future we will
have some jobs which set CROSS_STAGE=3 to produce native bindists for a
target, but produced by a cross compiler, which can be tested on by
another CI job on the native platform.
CROSS_STAGE=2: Build a normal cross compiler bindist
CROSS_STAGE=3: Build a stage 3 bindist, one which is a native compiler and library for the target
- - - - -
b763a64c by Matthew Pickering at 2026-01-16T08:23:45+01:00
hadrian: Refactor system-cxx-std-lib rules0
I noticed a few things wrong with the hadrian rules for `system-cxx-std-lib` rules.
* For `text` there is an ad-hoc check to depend on `system-cxx-std-lib` outside of `configurePackage`.
* The `system-cxx-std-lib` dependency is not read from cabal files.
* Recache is not called on the packge database after the `.conf` file is generated, a more natural place for this rule is `registerRules`.
Treating this uniformly like other packages is complicated by it not having any source code or a cabal file. However we can do a bit better by reporting the dependency firstly in `PackageData` and then needing the `.conf` file in the same place as every other package in `configurePackage`.
Fixes #25303
- - - - -
4da93fd0 by Sven Tennie at 2026-01-16T08:23:45+01:00
ci: Increase timeout for emulators
Test runs with emulators naturally take longer than on native machines.
Generate jobs.yml
- - - - -
9539bcbb by Sven Tennie at 2026-01-16T08:23:45+01:00
ghc: Distinguish between having an interpreter and having an internal one
Otherwise, we fail with warnings when compiling tools. Actually, these
are related but different things:
- ghc can run an interpreter (either internal or external)
- ghc is compiled with an internal interpreter
- - - - -
33c0850f by Matthew Pickering at 2026-01-16T08:23:45+01:00
ci: Javascript don't set CROSS_EMULATOR
There is no CROSS_EMULATOR needed to run javascript binaries, so we
don't set the CROSS_EMULATOR to some dummy value.
- - - - -
7936bd98 by Sven Tennie at 2026-01-16T08:23:45+01:00
Javascript skip T23697
See #22355 about how HSC2HS and the Javascript target don't play well
together.
- - - - -
acbce225 by Sven Tennie at 2026-01-16T08:23:45+01:00
Mark T24602 as fragile
It was skipped before (due to CROSS_EMULATOR being set, which changed
for JS), so we don't make things worse by marking it as fragile.
- - - - -
ebd8ff79 by Sven Tennie at 2026-01-16T08:23:45+01:00
WIP: Dirty hack
Let Stage0 build with the default.host.target file and decide for other
stages if default.target cannot be used.
Acutally, I don't like this logic on this level.
- - - - -
9f8c726a by Sven Tennie at 2026-01-16T08:23:45+01:00
Windows needs NM_STAGE0 as well
The stage0 always needs nm.
- - - - -
676d7b36 by Sven Tennie at 2026-01-16T08:23:45+01:00
T17912 sometimes works for windows-validate
This seems to be timing related. However, just simply increasing the
timeout (sleep) statement of this test didn't help. Maybe, it has been
flaky on CI before.
- - - - -
165 changed files:
- .gitlab/ci.sh
- .gitlab/generate-ci/gen_ci.hs
- .gitlab/jobs.yaml
- compiler/GHC/Cmm/Info.hs
- compiler/GHC/Cmm/Utils.hs
- compiler/GHC/CmmToLlvm/CodeGen.hs
- compiler/GHC/Core/Opt/OccurAnal.hs
- compiler/GHC/Core/Opt/SetLevels.hs
- compiler/GHC/Core/Opt/Simplify/Iteration.hs
- compiler/GHC/Core/Opt/Simplify/Utils.hs
- compiler/GHC/Core/Opt/SpecConstr.hs
- compiler/GHC/Core/Subst.hs
- compiler/GHC/Core/TyCo/Subst.hs
- compiler/GHC/Core/Utils.hs
- compiler/GHC/Driver/Backpack.hs
- compiler/GHC/Driver/Config/Interpreter.hs
- compiler/GHC/Driver/Downsweep.hs
- compiler/GHC/Driver/DynFlags.hs
- compiler/GHC/Driver/Pipeline.hs
- compiler/GHC/Driver/Pipeline/Execute.hs
- compiler/GHC/Driver/Session.hs
- compiler/GHC/Iface/Recomp.hs
- compiler/GHC/Linker/Dynamic.hs
- compiler/GHC/Linker/Executable.hs
- compiler/GHC/Linker/Loader.hs
- compiler/GHC/Linker/Unit.hs
- compiler/GHC/Settings.hs
- compiler/GHC/Settings/IO.hs
- compiler/GHC/StgToJS/Linker/Utils.hs
- compiler/GHC/Unit/Info.hs
- compiler/GHC/Unit/State.hs
- configure.ac
- distrib/configure.ac.in
- − docs/Makefile
- − docs/storage-mgt/Makefile
- − docs/users_guide/Makefile
- docs/users_guide/phases.rst
- − driver/Makefile
- − driver/ghc/Makefile
- − driver/ghci/Makefile
- − driver/haddock/Makefile
- ghc/GHC/Driver/Session/Mode.hs
- ghc/GHCi/UI.hs
- ghc/Main.hs
- − ghc/Makefile
- ghc/ghc-bin.cabal.in
- hadrian/README.md
- hadrian/bindist/config.mk.in
- hadrian/cfg/default.host.target.in
- hadrian/cfg/default.target.in
- + hadrian/cfg/system.config.host.in
- hadrian/cfg/system.config.in
- + hadrian/cfg/system.config.target.in
- hadrian/doc/flavours.md
- hadrian/hadrian.cabal
- hadrian/src/Base.hs
- + hadrian/src/BindistConfig.hs
- hadrian/src/Builder.hs
- hadrian/src/Context.hs
- hadrian/src/Expression.hs
- hadrian/src/Flavour.hs
- hadrian/src/Flavour/Type.hs
- hadrian/src/Hadrian/Builder.hs
- hadrian/src/Hadrian/Haskell/Cabal/Parse.hs
- hadrian/src/Hadrian/Haskell/Cabal/Type.hs
- hadrian/src/Hadrian/Haskell/Hash.hs
- hadrian/src/Hadrian/Oracles/TextFile.hs
- hadrian/src/Oracles/Flag.hs
- hadrian/src/Oracles/Flavour.hs
- hadrian/src/Oracles/Setting.hs
- hadrian/src/Oracles/TestSettings.hs
- hadrian/src/Packages.hs
- hadrian/src/Rules.hs
- hadrian/src/Rules/BinaryDist.hs
- hadrian/src/Rules/CabalReinstall.hs
- hadrian/src/Rules/Compile.hs
- hadrian/src/Rules/Documentation.hs
- hadrian/src/Rules/Generate.hs
- hadrian/src/Rules/Gmp.hs
- hadrian/src/Rules/Libffi.hs
- hadrian/src/Rules/Library.hs
- hadrian/src/Rules/Lint.hs
- hadrian/src/Rules/Program.hs
- hadrian/src/Rules/Register.hs
- hadrian/src/Rules/Rts.hs
- hadrian/src/Rules/Test.hs
- hadrian/src/Settings.hs
- hadrian/src/Settings/Builders/Cabal.hs
- hadrian/src/Settings/Builders/Common.hs
- hadrian/src/Settings/Builders/Configure.hs
- hadrian/src/Settings/Builders/DeriveConstants.hs
- hadrian/src/Settings/Builders/Ghc.hs
- hadrian/src/Settings/Builders/Hsc2Hs.hs
- hadrian/src/Settings/Builders/RunTest.hs
- hadrian/src/Settings/Builders/SplitSections.hs
- hadrian/src/Settings/Default.hs
- hadrian/src/Settings/Flavours/Benchmark.hs
- hadrian/src/Settings/Flavours/Development.hs
- hadrian/src/Settings/Flavours/GhcInGhci.hs
- hadrian/src/Settings/Flavours/Performance.hs
- hadrian/src/Settings/Flavours/Quick.hs
- hadrian/src/Settings/Flavours/QuickCross.hs
- hadrian/src/Settings/Flavours/Quickest.hs
- hadrian/src/Settings/Flavours/Validate.hs
- hadrian/src/Settings/Packages.hs
- hadrian/src/Settings/Program.hs
- hadrian/src/Settings/Warnings.hs
- − libraries/Makefile
- libraries/base/tests/IO/all.T
- libraries/base/tests/all.T
- − libraries/doc/Makefile
- libraries/ghc-boot/GHC/Unit/Database.hs
- libraries/ghc-internal/configure.ac
- libraries/ghc-internal/ghc-internal.buildinfo.in
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/include/HsIntegerGmp.h.in
- − linters/lint-codes/Makefile
- − linters/lint-notes/Makefile
- llvm-passes
- m4/fp_find_nm.m4
- + m4/fp_linker_supports_verbatim.m4
- m4/fptools_set_platform_vars.m4
- m4/prep_target_file.m4
- mk/system-cxx-std-lib-1.0.conf.in
- − rts/Makefile
- rts/configure.ac
- − rts/include/Makefile
- rts/rts.buildinfo.in
- rts/rts.cabal
- + testsuite/driver/_elffile.py
- testsuite/driver/testglobals.py
- testsuite/driver/testlib.py
- testsuite/ghc-config/ghc-config.hs
- + testsuite/tests/driver/fully-static/Hello.hs
- + testsuite/tests/driver/fully-static/Makefile
- + testsuite/tests/driver/fully-static/all.T
- + testsuite/tests/driver/fully-static/fully-static.stdout
- + testsuite/tests/driver/fully-static/test/Test.hs
- + testsuite/tests/driver/fully-static/test/test.pkg
- + testsuite/tests/driver/mostly-static/Hello.hs
- + testsuite/tests/driver/mostly-static/Makefile
- + testsuite/tests/driver/mostly-static/all.T
- + testsuite/tests/driver/mostly-static/mostly-static.stdout
- + testsuite/tests/driver/mostly-static/test/test.c
- + testsuite/tests/driver/mostly-static/test/test.h
- + testsuite/tests/driver/mostly-static/test/test.pkg
- + testsuite/tests/driver/recomp26705/M.hs
- + testsuite/tests/driver/recomp26705/M2A.hs
- + testsuite/tests/driver/recomp26705/M2B.hs
- + testsuite/tests/driver/recomp26705/Makefile
- + testsuite/tests/driver/recomp26705/all.T
- + testsuite/tests/driver/recomp26705/recomp26705.stderr
- testsuite/tests/ghc-e/should_fail/all.T
- testsuite/tests/javascript/closure/all.T
- + testsuite/tests/pmcheck/should_compile/T24867.hs
- + testsuite/tests/pmcheck/should_compile/T24867.stderr
- testsuite/tests/pmcheck/should_compile/all.T
- + testsuite/tests/simplCore/should_compile/T26681.hs
- + testsuite/tests/simplCore/should_compile/T26709.hs
- + testsuite/tests/simplCore/should_compile/T26709.stderr
- testsuite/tests/simplCore/should_compile/all.T
- utils/deriveConstants/Main.hs
- utils/ghc-pkg/Main.hs
- utils/ghc-toolchain/exe/Main.hs
- utils/ghc-toolchain/src/GHC/Toolchain/Tools/Link.hs
The diff was not included because it is too large.
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1f31ba989bd23e7a705ebb74df5f8d…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1f31ba989bd23e7a705ebb74df5f8d…
You're receiving this email because of your account on gitlab.haskell.org.
1
0
[Git][ghc/ghc][wip/26737] Make the implicit-parameter class have representational role
by Simon Peyton Jones (@simonpj) 16 Jan '26
by Simon Peyton Jones (@simonpj) 16 Jan '26
16 Jan '26
Simon Peyton Jones pushed to branch wip/26737 at Glasgow Haskell Compiler / GHC
Commits:
8ee3246a by Simon Peyton Jones at 2026-01-16T08:37:31+00:00
Make the implicit-parameter class have representational role
This MR addresses #26737, by making the built-in class IP
have a representational role for its second parameter.
See Note [IP: implicit parameter class] in
ghc-internal:GHC.Internal.Classes.IP
In fact, IP is (unfortunately, currently) exposed by
base:GHC.Base, so we ran a quick CLC proposal to
agree the change:
https://github.com/haskell/core-libraries-committee/issues/385
Some (small) compilations get faster because they only need to
load (small) interface file GHC.Internal.Classes.IP.hi,
rather than (large) GHC.Internal.Classes.hi,
Metric Decrease:
T10421
T12150
T12425
T24582
T5837
- - - - -
13 changed files:
- compiler/GHC/Builtin/Names.hs
- docs/users_guide/9.16.1-notes.rst
- libraries/ghc-internal/ghc-internal.cabal.in
- libraries/ghc-internal/src/GHC/Internal/Classes.hs
- + libraries/ghc-internal/src/GHC/Internal/Classes/IP.hs
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
- testsuite/tests/interface-stability/ghc-prim-exports.stdout
- testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
- testsuite/tests/th/TH_implicitParams.stdout
- + testsuite/tests/typecheck/should_compile/T26737.hs
- testsuite/tests/typecheck/should_compile/all.T
Changes:
=====================================
compiler/GHC/Builtin/Names.hs
=====================================
@@ -526,7 +526,7 @@ genericTyConNames = [
gHC_PRIM, gHC_PRIM_PANIC,
gHC_TYPES, gHC_INTERNAL_DATA_DATA, gHC_MAGIC, gHC_MAGIC_DICT,
- gHC_CLASSES, gHC_PRIMOPWRAPPERS :: Module
+ gHC_CLASSES, gHC_CLASSES_IP, gHC_PRIMOPWRAPPERS :: Module
gHC_PRIM = mkGhcInternalModule (fsLit "GHC.Internal.Prim") -- Primitive types and values
gHC_PRIM_PANIC = mkGhcInternalModule (fsLit "GHC.Internal.Prim.Panic")
gHC_TYPES = mkGhcInternalModule (fsLit "GHC.Internal.Types")
@@ -534,6 +534,7 @@ gHC_MAGIC = mkGhcInternalModule (fsLit "GHC.Internal.Magic")
gHC_MAGIC_DICT = mkGhcInternalModule (fsLit "GHC.Internal.Magic.Dict")
gHC_CSTRING = mkGhcInternalModule (fsLit "GHC.Internal.CString")
gHC_CLASSES = mkGhcInternalModule (fsLit "GHC.Internal.Classes")
+gHC_CLASSES_IP = mkGhcInternalModule (fsLit "GHC.Internal.Classes.IP")
gHC_PRIMOPWRAPPERS = mkGhcInternalModule (fsLit "GHC.Internal.PrimopWrappers")
gHC_INTERNAL_TUPLE = mkGhcInternalModule (fsLit "GHC.Internal.Tuple")
@@ -1521,7 +1522,7 @@ fromLabelClassOpName
-- Implicit Parameters
ipClassName :: Name
ipClassName
- = clsQual gHC_CLASSES (fsLit "IP") ipClassKey
+ = clsQual gHC_CLASSES_IP (fsLit "IP") ipClassKey
-- Overloaded record fields
hasFieldClassName :: Name
=====================================
docs/users_guide/9.16.1-notes.rst
=====================================
@@ -30,6 +30,18 @@ Language
- The extension :extension:`ExplicitNamespaces` now allows namespace-specified
wildcards ``type ..`` and ``data ..`` in import and export lists.
+- Implicit parameters and ``ImpredicativeTypes``. GHC now knows
+ that if ``?foo::S`` is coecible to ``?foo::T`` only if ``S`` is coercible to ``T``.
+ Example (from :ghc-ticket:`#26737`)::
+
+ {-# LANGUAGE ImplicitParams, ImpredicativeTypes #-}
+ newtype N = MkN Int
+ test :: ((?foo::N) => Bool) -> ((?foo::Int) => Bool)
+ test = coerce
+
+ This is achieved by arranging that ``?foo :: T`` has a representational
+ role for ``T``.
+
Compiler
~~~~~~~~
=====================================
libraries/ghc-internal/ghc-internal.cabal.in
=====================================
@@ -343,6 +343,7 @@ Library
GHC.Internal.CString
GHC.Internal.Classes
+ GHC.Internal.Classes.IP
GHC.Internal.Debug
GHC.Internal.Magic
GHC.Internal.Magic.Dict
=====================================
libraries/ghc-internal/src/GHC/Internal/Classes.hs
=====================================
@@ -1,10 +1,9 @@
{-# LANGUAGE Trustworthy #-}
{-# LANGUAGE NoImplicitPrelude, MagicHash, StandaloneDeriving, BangPatterns,
KindSignatures, DataKinds, ConstraintKinds,
- MultiParamTypeClasses, FunctionalDependencies #-}
-{-# LANGUAGE UnboxedTuples #-}
-{-# LANGUAGE AllowAmbiguousTypes #-}
- -- ip :: IP x a => a is strictly speaking ambiguous, but IP is magic
+ MultiParamTypeClasses, FunctionalDependencies,
+ UnboxedTuples #-}
+
{-# LANGUAGE UndecidableSuperClasses #-}
-- Because of the type-variable superclasses for tuples
@@ -142,6 +141,7 @@ import GHC.Internal.Prim
import GHC.Internal.Tuple
import GHC.Internal.CString (unpackCString#)
import GHC.Internal.Types
+import GHC.Internal.Classes.IP
infix 4 ==, /=, <, <=, >=, >
infixr 3 &&
@@ -149,12 +149,6 @@ infixr 2 ||
default () -- Double isn't available yet
--- | The syntax @?x :: a@ is desugared into @IP "x" a@
--- IP is declared very early, so that libraries can take
--- advantage of the implicit-call-stack feature
-class IP (x :: Symbol) a | x -> a where
- ip :: a
-
{- $matching_overloaded_methods_in_rules
Matching on class methods (e.g. @(==)@) in rewrite rules tends to be a bit
=====================================
libraries/ghc-internal/src/GHC/Internal/Classes/IP.hs
=====================================
@@ -0,0 +1,87 @@
+{-# LANGUAGE Trustworthy #-}
+{-# LANGUAGE NoImplicitPrelude, MagicHash, StandaloneDeriving, BangPatterns,
+ KindSignatures, DataKinds, ConstraintKinds,
+ MultiParamTypeClasses, FunctionalDependencies #-}
+
+{-# LANGUAGE AllowAmbiguousTypes, RoleAnnotations, IncoherentInstances #-}
+ -- LANGUAGE pragmas: see Note [IP: implicit parameter class]
+
+{-# OPTIONS_HADDOCK not-home #-}
+-----------------------------------------------------------------------------
+-- |
+-- Module : GHC.Internal.Classes.IP
+-- Copyright : (c) The University of Glasgow, 1992-2002
+-- License : see libraries/base/LICENSE
+--
+-- Maintainer : ghc-devs(a)haskell.org
+-- Stability : internal
+-- Portability : non-portable (GHC extensions)
+--
+-- Basic classes.
+-- Do not import this module directly. It is an GHC internal only
+-- module. Some of its contents are instead available from @Prelude@
+-- and @GHC.Int@.
+--
+-----------------------------------------------------------------------------
+
+module GHC.Internal.Classes.IP( IP(..)) where
+
+import GHC.Internal.Types
+
+
+default () -- Double isn't available yet
+
+-- | The syntax @?x :: a@ is desugared into @IP "x" a@
+-- IP is declared very early, so that libraries can take
+-- advantage of the implicit-call-stack feature
+type role IP nominal representational -- See (IPRoles)
+class IP (x :: Symbol) a | x -> a where
+ ip :: a
+
+{- Note [IP: implicit parameter class]
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+An implicit parameter constraint (?foo::ty) is just short for
+
+ IP "foo" ty
+
+where ghc-internal:GHC.Internal.Classes.IP is a special class that
+GHC knows about, defined in this module.
+
+* It is a unary type class, with one method `ip`, so it has no cost.
+ For example, (?foo::Int) is represented just by an Int.
+
+* Criticially, it has a functional dependency:
+ class IP (x :: Symbol) a | x -> a where ...
+ So if we have
+ [G] IP "foo" Int
+ [W] IP "foo" alpha
+ the fundep wil lgive us alpha ~ Int, as desired.
+
+* The solver has a number of special cases for implicit parameters,
+ mainly because a binding (let ?foo::Int = rhs in body)
+ is like a local instance declaration for IP. Search for uses
+ of `isIPClass`.
+
+Wrinkles
+
+(IPAmbiguity) The single method of IP has an ambiguous type
+ ip :: forall a. IP s a => a
+ Hence the LANGUAGE pragama AllowAmbiguousTypes.
+ The method `ip` is never called by the user, so ambiguity doesn't matter.
+
+(IPRoles) IP has a role annotation. Why? See #26737. We want
+ [W] IP "foo" t1 ~R# IP "foo" t2
+ to decompose to give [W] IP t1 ~R# t2, using /representational/
+ equality for (t1 ~R# t2) not nominal.
+
+ This usually gives a complaint about incoherence, because in general
+ (t1 ~R# t2) does NOT imply (C t1) ~R# (C t2) for any normal class.
+ But it does for IP, because instance selection is controlled by the Symbol,
+ not the type of the payload. Hence LANGUAGE pragma IncoherentInstances.
+ (It is unfortunate that we need a module-wide IncoherentInstances here;
+ see #17167.)
+
+ Side note: arguably this treatment could be applied to any class
+ with a functional dependency; but for now we restrict it to IP.
+-}
+
=====================================
testsuite/tests/interface-stability/base-exports.stdout
=====================================
@@ -3293,6 +3293,7 @@ module GHC.Base where
{-# MINIMAL fmap #-}
type IO :: * -> *
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
+ type role IP nominal representational
type IP :: Symbol -> * -> Constraint
class IP x a | x -> a where
ip :: a
=====================================
testsuite/tests/interface-stability/base-exports.stdout-mingw32
=====================================
@@ -3293,6 +3293,7 @@ module GHC.Base where
{-# MINIMAL fmap #-}
type IO :: * -> *
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
+ type role IP nominal representational
type IP :: Symbol -> * -> Constraint
class IP x a | x -> a where
ip :: a
=====================================
testsuite/tests/interface-stability/base-exports.stdout-ws-32
=====================================
@@ -3293,6 +3293,7 @@ module GHC.Base where
{-# MINIMAL fmap #-}
type IO :: * -> *
newtype IO a = IO (State# RealWorld -> (# State# RealWorld, a #))
+ type role IP nominal representational
type IP :: Symbol -> * -> Constraint
class IP x a | x -> a where
ip :: a
=====================================
testsuite/tests/interface-stability/ghc-prim-exports.stdout
=====================================
@@ -1171,6 +1171,7 @@ module GHC.Classes where
(==) :: a -> a -> GHC.Internal.Types.Bool
(/=) :: a -> a -> GHC.Internal.Types.Bool
{-# MINIMAL (==) | (/=) #-}
+ type role IP nominal representational
type IP :: GHC.Internal.Types.Symbol -> * -> Constraint
class IP x a | x -> a where
ip :: a
=====================================
testsuite/tests/interface-stability/ghc-prim-exports.stdout-mingw32
=====================================
@@ -1171,6 +1171,7 @@ module GHC.Classes where
(==) :: a -> a -> GHC.Internal.Types.Bool
(/=) :: a -> a -> GHC.Internal.Types.Bool
{-# MINIMAL (==) | (/=) #-}
+ type role IP nominal representational
type IP :: GHC.Internal.Types.Symbol -> * -> Constraint
class IP x a | x -> a where
ip :: a
=====================================
testsuite/tests/th/TH_implicitParams.stdout
=====================================
@@ -1,5 +1,5 @@
-Main.funcToReify :: GHC.Internal.Classes.IP "z"
- GHC.Internal.Types.Int =>
+Main.funcToReify :: GHC.Internal.Classes.IP.IP "z"
+ GHC.Internal.Types.Int =>
GHC.Internal.Types.Int
5
1
=====================================
testsuite/tests/typecheck/should_compile/T26737.hs
=====================================
@@ -0,0 +1,10 @@
+{-# LANGUAGE ImpredicativeTypes, ImplicitParams #-}
+
+module T26737 where
+
+import Data.Coerce
+
+newtype Foo = MkFoo Int
+
+b :: ((?foo :: Foo) => Int) -> ((?foo :: Int) => Int)
+b = coerce @(((?foo :: Foo) => Int)) @(((?foo :: Int) => Int))
=====================================
testsuite/tests/typecheck/should_compile/all.T
=====================================
@@ -957,3 +957,4 @@ test('T17705', normal, compile, [''])
test('T14745', normal, compile, [''])
test('T26451', normal, compile, [''])
test('T26582', normal, compile, [''])
+test('T26737', normal, compile, [''])
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8ee3246a227b22459e85c845d382509…
--
View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/commit/8ee3246a227b22459e85c845d382509…
You're receiving this email because of your account on gitlab.haskell.org.
1
0