[Git][ghc/ghc][ghc-9.12] 25 commits: OccAnal: Be stricter for better compiler perf.
Zubin pushed to branch ghc-9.12 at Glasgow Haskell Compiler / GHC Commits: 22334776 by Andreas Klebinger at 2026-03-11T11:04:15+05:30 OccAnal: Be stricter for better compiler perf. In particular we are now stricter: * When combining usageDetails. * When computing binder info. In combineUsageDetails when combining the underlying adds we compute a new `LocalOcc` for each entry by combining the two existing ones. Rather than wait for those entries to be forced down the road we now force them immediately. Speeding up T26425 by about 10% with little effect on the common case. We also force binders we put into the Core AST everywhere now. Failure to do so risks leaking the occ env used to set the binders OccInfo. For T26425 compiler residency went down by a factor of ~10x. Compile time also improved by a factor of ~1.6. ------------------------- Metric Decrease: T18698a T26425 T9233 ------------------------- (cherry picked from commit f997618e08ce5aad8b7564b8073889b52bc18700) - - - - - 69cdf81a by Andreas Klebinger at 2026-03-11T11:04:24+05:30 Add a perf test for #26425 (cherry picked from commit 4038a28b8594ae91c000d5bc7fceed4815eb4826) - - - - - 56a259ec by sheaf at 2026-03-11T11:05:48+05:30 Update assigned register format when spilling When we come to spilling a register to put new data into it, in GHC.CmmToAsm.Reg.Linear.allocRegsAndSpill_spill, we need to: 1. Spill the data currently in the register. That is, do a spill with a format that matches what's currently in the register. 2. Update the register assignment, allocating a virtual register to this real register, but crucially **updating the format** of this assignment. Due to shadowing in the Haskell code for allocRegsAndSpill_spill, we were mistakenly re-using the old format. This could lead to a situation where: a. We were using xmm6 to store a Double#. b. We want to store a DoubleX2# into xmm6, so we spill the current content of xmm6 to the stack using a scalar move (correct). c. We update the register assignment, but we fail to update the format of the assignment, so we continue to think that xmm6 stores a Double# and not a DoubleX2#. d. Later on, we need to spill xmm6 because it is getting clobbered by another instruction. We then decide to only spill the lower 64 bits of the register, because we still think that xmm6 only stores a Double# and not a DoubleX2#. Fixes #26542 (cherry picked from commit 79dfcfe008af5e04c0f51cc2a3709ee08aebd59b) - - - - - 48836e62 by sheaf at 2026-03-11T11:06:00+05:30 localRegistersConflict: account for assignment LHS This commit fixes a serious oversight in GHC.Cmm.Sink.conflicts, specifically the code that computes which local registers conflict between an assignment and a Cmm statement. If we have: assignment: <local_reg> = <expr> node: <local_reg> = <other_expr> then clearly the two conflict, because we cannot move one statement past the other, as they assign two different values to the same local register. (Recall that 'conflicts (local_reg,expr) node' is False if and only if the assignment 'local_reg = expr' can be safely commuted past the statement 'node'.) The fix is to update 'GHC.Cmm.Sink.localRegistersConflict' to take into account the following two situations: (1) 'node' defines the LHS local register of the assignment, (2) 'node' defines a local register used in the RHS of the assignment. The bug is precisely that we were previously missing condition (1). Fixes #26550 (cherry picked from commit 43fa8be89bdccbbe730daf0be7bdae8dde99ce44) - - - - - 046d8a80 by ARATA Mizuki at 2026-03-11T11:06:12+05:30 Fix the order of spill/reload instructions The AArch64 NCG could emit multiple instructions for a single spill/reload, but their order was not consistent between the definition and a use. Fixes #26537 Co-authored-by: sheaf <sam.derbyshire@gmail.com> (cherry picked from commit aada5db93a2f0fd00c0715ad9ca4f666ffb3d9d8) - - - - - f538aea7 by Luite Stegeman at 2026-03-11T11:07:02+05:30 rts: Handle overflow of ELF section header string table If the section header string table is stored in a section greater than or equal to SHN_LORESERVE (0xff00), the 16-bit field e_shstrndx in the ELF header does not contain the section number, but rather an overflow value SHN_XINDEX (0xffff) indicating that we need to look elsewhere. This fixes the linker by not using e_shstrndx directly but calling elf_shstrndx, which correctly handles the SHN_XINDEX value. Fixes #26603 (cherry picked from commit c71faa7697f2d0bc8b92173aeb1f063ca8ed235a) - - - - - 3081de58 by Peter Trommler at 2026-03-11T11:07:13+05:30 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 (cherry picked from commit c1fe009739da8b368e59b87b00d7c568ab571643) - - - - - d3c9cd0f by Aaron Allen at 2026-03-11T11:10:02+05:30 [#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 (cherry picked from commit 8a317b6f6d007b7cb5f2d661849383042892b3d8) - - - - - 00ad5059 by Aaron Allen at 2026-03-11T11:11:02+05:30 [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 (cherry picked from commit 8a3900a325a8f476d1e31a84deeab934b9161801) - - - - - 9a3dc83e by Vladislav Zavialov at 2026-03-11T11:11:45+05:30 Check for negative type literals in the type checker (#26861) GHC disallows negative type literals (e.g., -1), as tested by T8306 and T8412. This check is currently performed in the renamer: rnHsTyLit tyLit@(HsNumTy x i) = do when (i < 0) $ addErr $ TcRnNegativeNumTypeLiteral tyLit However, this check can be bypassed using RequiredTypeArguments (see the new test case T26861). Prior to this patch, such programs caused the compiler to hang instead of reporting a proper error. This patch addresses the issue by adding an equivalent check in the type checker, namely in tcHsType. The diff is deliberately minimal to facilitate backporting. A more comprehensive rework of HsTyLit is planned for a separate commit. (cherry picked from commit bd3eba86180083a3bd1633994b9e6cd3be501a1d) - - - - - 1945b61d by Sylvain Henry at 2026-03-11T11:13:17+05:30 Linker: implement support for COMMON symbols (#6107) Add some support for COMMON symbols. We don't support common symbols having different sizes where the larger one is allocated after the smaller one. The linker will fail with an appropriate error message if it happens. (cherry picked from commit ad25af90bdbf1269ff9febbcbc9fffa804b11bda) - - - - - 40f0623b by sheaf at 2026-03-11T11:13:35+05:30 System.Info.fullCompilerVersion: add 'since' annot Fixes #26973 (cherry picked from commit fc8b8e27398b4d9d901fb65d15a7d8b23df428b8) - - - - - 02a98d4a by sheaf at 2026-03-11T12:29:53+05:30 NamedDefaults: handle poly-kinded unary classes With this commit, we accept named default declarations for poly-kinded classes such as Typeable, e.g. default Typeable (Char) This used to fail because we assumed the kind of the class was monomorphic, e.g. Type -> Constraint (Type -> Type) -> Constraint Nat -> Constraint Now, we can handle a simple polymorphic class such as Typeable :: forall k. k -> Constraint Note that we keep the restriction that the class must only have one visible argument. This is all explained in the new Note [Instance check for default declarations] in GHC.Tc.Gen.Default. Fixes #25882 (cherry picked from commit d99eb7cd157e0d8e1dedfa862161502755c26e5b) - - - - - f0244f6a by Recursion Ninja at 2026-03-11T13:45:10+05:30 Resolving issues #20645 and #26109 Correctly sign extending and casting smaller bit width types for LLVM operations: - bitReverse8# - bitReverse16# - bitReverse32# - byteSwap16# - byteSwap32# - pdep8# - pdep16# - pext8# - pext16# (cherry picked from commit 706d33e38fbdcea3f84c34c727c55cfb98c74990) - - - - - 062de3a5 by Alex Washburn at 2026-03-11T13:56:36+05:30 Correcting LLVM linking of Intel BMI intrinsics pdep{8,16} and pext{8,16}. This patch fixes #26065. The LLVM interface does not expose bindings to: - llvm.x86.bmi.pdep.8 - llvm.x86.bmi.pdep.16 - llvm.x86.bmi.pext.8 - llvm.x86.bmi.pext.16 So calls are instead made to llvm.x86.bmi.{pdep,pext}.32 in these cases, with pre/post-operation truncation to constrain the logical value range. (cherry picked from commit 0a601c30d5e885d9b15b202f1fce55ca263315fb) - - - - - c1883c7e by Zubin Duggal at 2026-03-11T14:25:36+05:30 Revert "Don't re-use stack slots for growing registers" This reverts commit 59cc8e6823e7ebe13525fe47b57967b19fc6ff41. - - - - - 01e4bbdb by sheaf at 2026-03-11T14:26:11+05:30 X86 CodeGen: fix assign_eax_sse_regs We must set %al to the number of SSE2 registers that contain arguments (in case we are dealing with a varargs function). The logic for counting how many arguments reside in SSE2 registers was incorrect, as it used 'isFloatFormat', which incorrectly ignores vector registers. We now instead do case analysis on the register class: is_sse_reg r = case targetClassOfReg platform r of RcFloatOrVector -> True RcInteger -> False This change is necessary to prevent segfaults in T20030_test1j, because subsequent commits change the format calculations, resulting in vector formats more often. (cherry picked from commit fca9cd7ce4abc4320c66f6a619063b2c66890504) - - - - - bf3aa49f by sheaf at 2026-03-11T14:26:24+05:30 X86 regUsageOfInstr: fix format for IMUL When used with 8-bit operands, the IMUL instruction returns the result in the lower 16 bits of %rax (also known as %ax). This is different than for the other sizes, where an input at 16, 32 or 64 bits will result in 16, 32 or 64 bits of output in both %rax and %rdx. This doesn't affect the behaviour of the compiler, because we don't allow partial writes at sub-word sizes. The rationale is explained in Wrinkle [Don't allow scalar partial writes] in Note [Register formats in liveness analysis], in GHC.CmmToAsm.Reg.Liveness. (cherry picked from commit 53150617c8648635b0fbfc4144f04c53e7180a60) - - - - - d999d711 by sheaf at 2026-03-11T15:00:34+05:30 Liveness analysis: consider register formats This commit updates the register allocator to be a bit more careful in situations in which a single register is used at multiple different formats, e.g. when xmm1 is used both to store a Double# and a DoubleX2#. This is done by introducing the 'Regs' newtype around 'UniqSet RegWithFormat', for which the combining operations take the larger of the two formats instead of overriding the format. Operations on 'Regs' are defined in 'GHC.CmmToAsm.Reg.Regs'. There is a modest compile-time cost for the additional overhead for tracking register formats, which causes the metric increases of this commit. The subtle aspects of the implementation are outlined in Note [Register formats in liveness analysis] in GHC.CmmToAsm.Reg.Liveness. Fixes #26411 #26611 ------------------------- Metric Increase: T12707 T26425 T3294 ------------------------- (cherry picked from commit c7a56dd1ea2b8bd4cd9dc4a46e07c589db559383) - - - - - 38e53aea by sheaf at 2026-03-11T15:03:55+05:30 Register allocator: reload at same format as spill This commit ensures that if we spill a register onto the stack at a given format, we then always reload the register at this same format. This ensures we don't end up in a situation where we spill F64x2 but end up only reloading the lower F64. This first reload would make us believe the whole data is in a register, thus silently losing the upper 64 bits of the spilled register's contents. Fixes #26526 (cherry picked from commit c2e83339593bc31a82a0fdb7f11fa693324f9804) - - - - - 254008d7 by sheaf at 2026-03-11T15:04:06+05:30 Register allocation: writes redefine format As explained in Note [Allocated register formats] in GHC.CmmToAsm.Reg.Linear, we consider all writes to redefine the format of the register. This ensures that in a situation such as movsd .Ln6m(%rip),%v1 shufpd $0,%v1,%v1 we properly consider the broadcast operation to change the format of %v1 from F64 to F64x2. This completes the fix to #26411 (test in T26411b). (cherry picked from commit 55ab583b40ecdc1abc3307cea1d6a2c958a5ed29) - - - - - 5f311f5e by sheaf at 2026-03-11T15:04:18+05:30 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 (cherry picked from commit 023c301c51e7346af3d4d773c448277ad3645ad2) - - - - - 11be0bb5 by Simon Peyton Jones at 2026-03-11T15:27:16+05:30 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@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. (cherry picked from commit 641ec3f01974dff9dfd756f3f0499796c8df1a8b) - - - - - 2f5da16e by Zubin Duggal at 2026-03-11T15:30:20+05:30 Revert "rts: fix eager black holes: record mutated closure and fix assertion" This reverts commit f162eb8f08fa661183c5168cce077d5e9b4ebc03. - - - - - 097556ce by Zubin Duggal at 2026-03-12T00:21:29+05:30 Release notes for 9.12.4 Metric Increase: T4801 - - - - - 94 changed files: - compiler/GHC/Builtin/primops.txt.pp - compiler/GHC/Cmm/Sink.hs - compiler/GHC/CmmToAsm/PPC/CodeGen.hs - compiler/GHC/CmmToAsm/Reg/Graph.hs - compiler/GHC/CmmToAsm/Reg/Graph/Coalesce.hs - compiler/GHC/CmmToAsm/Reg/Graph/Spill.hs - compiler/GHC/CmmToAsm/Reg/Graph/SpillCost.hs - compiler/GHC/CmmToAsm/Reg/Linear.hs - compiler/GHC/CmmToAsm/Reg/Linear/Base.hs - compiler/GHC/CmmToAsm/Reg/Linear/JoinToTargets.hs - compiler/GHC/CmmToAsm/Reg/Liveness.hs - + compiler/GHC/CmmToAsm/Reg/Regs.hs - compiler/GHC/CmmToAsm/Reg/Target.hs - compiler/GHC/CmmToAsm/X86/CodeGen.hs - compiler/GHC/CmmToAsm/X86/Instr.hs - compiler/GHC/CmmToLlvm/CodeGen.hs - compiler/GHC/Core/Opt/OccurAnal.hs - compiler/GHC/Core/Opt/Specialise.hs - compiler/GHC/Iface/Recomp.hs - compiler/GHC/Tc/Deriv.hs - compiler/GHC/Tc/Errors/Ppr.hs - compiler/GHC/Tc/Errors/Types.hs - compiler/GHC/Tc/Gen/Default.hs - compiler/GHC/Tc/Gen/HsType.hs - compiler/GHC/Tc/Solver.hs - compiler/GHC/Types/Unique/FM.hs - compiler/GHC/Types/Unique/Set.hs - compiler/GHC/Types/Var/Env.hs - compiler/ghc.cabal.in - docs/users_guide/9.12.4-notes.rst - docs/users_guide/exts/named_defaults.rst - libraries/base/src/System/Info.hs - rts/Linker.c - rts/LinkerInternals.h - rts/ThreadPaused.c - rts/linker/Elf.c - rts/linker/MachO.c - rts/linker/PEi386.c - rts/prim/pdep.c - + testsuite/tests/codeGen/should_run/T26537.hs - + testsuite/tests/codeGen/should_run/T26537.stdout - testsuite/tests/codeGen/should_run/all.T - + testsuite/tests/default/T25882.hs - testsuite/tests/default/all.T - testsuite/tests/default/default-fail01.stderr - testsuite/tests/default/default-fail02.stderr - testsuite/tests/default/default-fail04.stderr - testsuite/tests/default/default-fail08.stderr - + 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/llvm/should_run/T20645.hs - + testsuite/tests/llvm/should_run/T20645.stdout - + testsuite/tests/llvm/should_run/T26065.hs - + testsuite/tests/llvm/should_run/T26065.stdout - testsuite/tests/llvm/should_run/all.T - testsuite/tests/numeric/should_run/foundation.hs - + testsuite/tests/perf/compiler/T26425.hs - testsuite/tests/perf/compiler/all.T - testsuite/tests/rts/linker/Makefile - + testsuite/tests/rts/linker/T6107.hs - + testsuite/tests/rts/linker/T6107.stdout - + testsuite/tests/rts/linker/T6107_sym1.s - + testsuite/tests/rts/linker/T6107_sym2.s - testsuite/tests/rts/linker/all.T - + testsuite/tests/simd/should_run/T26411.hs - + testsuite/tests/simd/should_run/T26411.stdout - + testsuite/tests/simd/should_run/T26411b.hs - + testsuite/tests/simd/should_run/T26411b.stdout - + testsuite/tests/simd/should_run/T26542.hs - + testsuite/tests/simd/should_run/T26542.stdout - + testsuite/tests/simd/should_run/T26550.hs - + testsuite/tests/simd/should_run/T26550.stdout - testsuite/tests/simd/should_run/all.T - + testsuite/tests/simplCore/should_compile/T26682.hs - + testsuite/tests/simplCore/should_compile/T26682a.hs - testsuite/tests/simplCore/should_compile/all.T - + testsuite/tests/typecheck/should_fail/T26861.hs - + testsuite/tests/typecheck/should_fail/T26861.stderr - testsuite/tests/typecheck/should_fail/all.T - utils/genprimopcode/Lexer.x - utils/genprimopcode/Main.hs - utils/genprimopcode/Parser.y - utils/genprimopcode/ParserM.hs - utils/genprimopcode/Syntax.hs The diff was not included because it is too large. View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1070cf051bc110175dd29bc142d4fe3... -- View it on GitLab: https://gitlab.haskell.org/ghc/ghc/-/compare/1070cf051bc110175dd29bc142d4fe3... You're receiving this email because of your account on gitlab.haskell.org.
participants (1)
-
Zubin (@wz1000)