Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Remove x86 per-source-register write barrier helpers - #128797

Closed
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup
Closed

Remove x86 per-source-register write barrier helpers#128797
EgorBo wants to merge 2 commits into
dotnet:mainfrom
EgorBo:egor/x86-wb-cleanup

Conversation

@EgorBo

Copy link
Copy Markdown
Member

Removes the per-source-register x86 write barrier helpers (CORINFO_HELP_ASSIGN_REF_EAX etc.) and the related dead infrastructure across the JIT-EE interface, R2R format, AOT tools, and the CoreCLR + NativeAOT runtimes. The JIT now always emits the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF on x86, matching x64.

Bumps JITEEVersionIdentifier and R2R major version (19 → 20).

Note

This pull request was created with help from GitHub Copilot.

Match what x64 and other targets already do: always emit a call to the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF helper instead of selecting between per-source-register specialized helpers (CORINFO_HELP_ASSIGN_REF_EAX, etc.).
The runtime universal helper already has the narrow ABI: ecx = dst, edx = src, only eax/edx trashed, all callee-saved registers and ecx preserved. The JIT continues to use RBM_CALLEE_TRASH_WRITEBARRIER (RBM_EAX | RBM_EDX) as the kill set, so it knows what's preserved across the call.
This follows the same JIT-only first-step pattern as dotnet#128542 (Remove CORINFO_HELP_ASSIGN_BYREF). The enum values, jithelpers.h, readytorunhelpers.h, R2R format, runtime asm helpers (jithelp.asm/S, WriteBarriers.asm/S), jitinterfacex86.cpp, excep.cpp, and AOT tools are intentionally left alone for a follow-up cleanup similar to dotnet#128687.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
CopilotAI review requested due to automatic review settings May 30, 2026 04:42
@github-actionsgithub-actionsBot added the area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI label May 30, 2026
@dotnet-policy-service

Copy link
Copy Markdown
Contributor

Tagging subscribers to this area: @JulieLeeMSFT, @jakobbotsch
See info in area-owners.md if you want to be subscribed.

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Removes the per-source-register x86 write barrier infrastructure (CORINFO_HELP_ASSIGN_REF_<reg> / CORINFO_HELP_CHECKED_ASSIGN_REF_<reg> and the matching Rhp*Reg, JIT_WriteBarrier<reg>, READYTORUN_HELPER_WriteBarrier_<reg> helpers) so x86 codegen always uses the unified CORINFO_HELP_ASSIGN_REF / CORINFO_HELP_CHECKED_ASSIGN_REF with a fixed ECX = dst, EDX = src ABI, matching x64. JIT-EE GUID and R2R major version are bumped to reflect the breaking change.

Changes:

  • Delete per-register helpers from CorInfo, jithelpers, ReadyToRun, AOT tools, CoreCLR i386 asm/cpp, NativeAOT i386 asm and EH tables.
  • Collapse JIT write-barrier lowering on x86 to the unified path (genUseOptimizedWriteBarriers, NOGC_WRITE_BARRIERS, per-arch defines, and genEmitOptimizedGCWriteBarrier all removed).
  • Bump JITEEVersionIdentifier, READYTORUN_MAJOR_VERSION and MINIMUM_READYTORUN_MAJOR_VERSION from 19 to 20; mark the old R2R helper IDs as unused.

Reviewed changes

Copilot reviewed 36 out of 36 changed files in this pull request and generated no comments.

Show a summary per file
FileDescription
src/coreclr/inc/corinfo.h, tools/Common/JitInterface/CorInfoHelpFunc.csRemove CORINFO_HELP_(CHECKED_)ASSIGN_REF_<reg> enum entries
src/coreclr/inc/jithelpers.hDrop x86 per-register Rhp(Checked)AssignRef<reg> mappings
src/coreclr/inc/jiteeversionguid.hBump JIT/EE GUID
src/coreclr/inc/readytorun.h, readytorunhelpers.h, tools/Common/Internal/Runtime/ReadyToRunConstants.cs, ModuleHeaders.cs, nativeaot/Runtime/inc/ModuleHeaders.hBump R2R version to 20 and annotate retired x86 helper IDs
src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/JitHelper.cs, ILCompiler.ReadyToRun/.../CorInfoImpl.ReadyToRun.cs, ILCompiler.RyuJit/.../CorInfoImpl.RyuJit.cs, ILCompiler.Reflection.ReadyToRun/ReadyToRunSignature.csRemove AOT/R2R mappings + display names for the deleted helpers
src/coreclr/jit/codegencommon.cpp, codegeninterface.h, codegen.h, codegenxarch.cpp, lsrabuild.cpp, utils.cppDrop genUseOptimizedWriteBarriers / genEmitOptimizedGCWriteBarrier / RBM_OPTIMIZED_WRITE_BARRIER_* and per-register kill-sets; route x86 through unified helper
src/coreclr/jit/targetx86.h, targetamd64.h, targetarm.h, targetarm64.h, targetloongarch64.h, targetriscv64.h, targetwasm.hRemove NOGC_WRITE_BARRIERS and RBM_OPTIMIZED_WRITE_BARRIER_* defines; update x86 write-barrier ABI comments
src/coreclr/vm/jitinterface.h, threads.cpp, i386/jithelp.asm, i386/jithelp.S, i386/jitinterfacex86.cppKeep only the EAX template; simplify init/patch/stomp logic; remove per-register init loop
src/coreclr/vm/excep.cpp, nativeaot/Runtime/EHHelpers.cppDrop x86 per-register Rhp(Checked)AssignRef<reg>AVLocation AV tables
src/coreclr/runtime/i386/WriteBarriers.asm, WriteBarriers.SRemove the per-source-register DEFINE_(CHECKED_)WRITE_BARRIER EDX, <reg> instantiations
docs/design/coreclr/botr/readytorun-format.mdAnnotate retired x86 R2R write-barrier helper IDs

@jakobbotsch

jakobbotsch commented May 30, 2026

Copy link
Copy Markdown
Member

Isn't this just a deoptimization? What is the motivation?
We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

@EgorBo

Copy link
Copy Markdown
MemberAuthor

Isn't this just a deoptimization? What is the motivation? We have multiple PRs clashing over taking R2R version changes (#128664, #128706, #128397) so I would suggest waiting until the dust settles with some of this.

The motiviation is simplification if the diffs imply it's not worth having multiple versions of WB and +700 LOC. My assumption was "if we don't do this on any other arch - maybe it's not worth it?" I'm fine keeping this open till other PRs you listed land.

@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 75d9d11 to 6fcdf3bCompareMay 30, 2026 12:56
CopilotAI review requested due to automatic review settings May 30, 2026 13:12
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 6fcdf3b to 69d63c6CompareMay 30, 2026 13:12

CopilotAI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 32 out of 32 changed files in this pull request and generated 3 comments.

Comment threadsrc/coreclr/inc/corinfo.h Outdated
Comment threadsrc/coreclr/tools/Common/JitInterface/CorInfoHelpFunc.cs Outdated
Comment threadsrc/coreclr/inc/readytorun.h Outdated
… code
Follow-up to the prior JIT-only cleanup. Removes the now-dead infrastructure for the per-source-register x86 write barriers across the JIT-EE interface, R2R format, AOT tools (crossgen2 / NativeAOT compiler), and the CoreCLR + NativeAOT runtimes.
Changes:
- JIT-EE interface: remove the 12 CORINFO_HELP_(CHECKED_)ASSIGN_REF_E[reg] enum values from corinfo.h, jithelpers.h, and the managed mirror; bump JITEEVersionIdentifier; remove the X86 case-label block in utils.cpp's HelperCallProperties::init.
- R2R format: bump major version to 20; mark slots 0x100-0x10B (READYTORUN_HELPER_(Checked)WriteBarrier_E[reg]) as unused (kept for image-compat parsing); update botr/readytorun-format.md, ModuleHeaders.h/cs, ReadyToRunConstants.cs; remove HELPER() lines in readytorunhelpers.h.
- AOT tools: remove switch cases in CorInfoImpl.RyuJit.cs, CorInfoImpl.ReadyToRun.cs, ReadyToRunSignature.cs, and JitHelper.cs.
- NativeAOT runtime: remove the per-register DEFINE_(CHECKED_)WRITE_BARRIER invocations and the corresponding RhpAssignRefE[reg]AVLocation references in EHHelpers.cpp.
- CoreCLR x86 VM: remove all per-register variants except EAX from vm/i386/jithelp.asm/.S (EAX is kept as the patched target of the universal @JIT_WriteBarrier@8 trampoline). Drop the never-called @JIT_CheckedWriteBarrier@8 trampoline entirely (x86's CORINFO_HELP_CHECKED_ASSIGN_REF maps to RhpCheckedAssignRef, not JIT_CheckedWriteBarrier). Simplify the c_rgWriteBarriers/c_rgDebugWriteBarriers tables and patching loops in vm/i386/jitinterfacex86.cpp to operate on the single EAX entry. Drop the dead per-reg AV location declarations from vm/excep.cpp and the X86_WRITE_BARRIER_REGISTER macro in vm/threads.cpp and vm/jitinterface.h.
Validation: clr+libs builds cleanly for x86 and x64; clr.tools and clr.nativeaotruntime build cleanly; x64 GC write-barrier exercising test passes with the rebuilt JIT (exit 100). The same x86 e2e test cannot be run on this machine due to a pre-existing testhost startup issue that affects baseline main as well.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@EgorBo
EgorBoforce-pushed the egor/x86-wb-cleanup branch from 69d63c6 to d9ac263CompareMay 30, 2026 13:51
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Seems like it's quite a big size regression (obviously, I did expect it, but not that big):

Found 474 files with textual diffs.
Summary of Code Size diffs:
(Lower is better)
Total bytes of base: 61393713
Total bytes of diff: 62753916
Total bytes of delta: 1360203 (2.22 % of base)
Total relative delta: NaN
diff is a regression.
relative diff is a regression.
Top file regressions (bytes):
244175 : Microsoft.CodeAnalysis.CSharp.dasm (3.02% of base)
194476 : Microsoft.CodeAnalysis.VisualBasic.dasm (3.13% of base)
92669 : Microsoft.Diagnostics.Tracing.TraceEvent.dasm (2.98% of base)
88840 : System.Private.Xml.dasm (2.82% of base)
86927 : System.Linq.Parallel.dasm (5.37% of base)
81700 : Microsoft.CodeAnalysis.dasm (1.85% of base)
58590 : System.Private.CoreLib.dasm (0.91% of base)
43821 : FSharp.Core.dasm (6.43% of base)
23036 : CommandLine.dasm (5.38% of base)
19631 : System.Collections.Immutable.dasm (1.15% of base)
18174 : System.Threading.Tasks.Dataflow.dasm (1.87% of base)
17458 : System.Data.Common.dasm (1.38% of base)
16912 : System.Linq.Expressions.dasm (2.62% of base)
16682 : System.Text.Json.dasm (1.32% of base)
16106 : System.Management.dasm (5.86% of base)
15203 : System.Linq.dasm (1.36% of base)
14865 : System.Net.Http.dasm (2.14% of base)
14199 : Newtonsoft.Json.dasm (1.89% of base)
13796 : System.Security.Cryptography.dasm (1.41% of base)
12744 : Microsoft.CSharp.dasm (4.06% of base)
12257 : System.Text.RegularExpressions.dasm (2.07% of base)
12080 : System.Collections.dasm (2.25% of base)
11967 : System.Private.DataContractSerialization.dasm (1.70% of base)
10594 : System.Linq.AsyncEnumerable.dasm (0.50% of base)
8537 : System.DirectoryServices.AccountManagement.dasm (2.89% of base)
Top file improvements (bytes):
-8 : System.Security.Cryptography.ProtectedData.dasm (-0.15% of base)
-2 : System.Runtime.CompilerServices.VisualC.dasm (-8.00% of base)
191 total files with Code Size differences (2 improved, 189 regressed), 90 unchanged.
Top method regressions (bytes):
3792 (25.94% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:.cctor() (FullOpts)
2662 (14.21% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrPrivateTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
2456 (13.94% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.ClrTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1933 (22.94% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADStoreCtx:.cctor() (FullOpts)
1537 (20.31% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.ADAMStoreCtx:.cctor() (FullOpts)
1517 (26.06% of base) : System.Private.Xml.dasm - System.Xml.Schema.DatatypeImplementation:.cctor() (FullOpts)
1491 (17.37% of base) : System.DirectoryServices.AccountManagement.dasm - System.DirectoryServices.AccountManagement.SAMStoreCtx:.cctor() (FullOpts)
1362 (16.53% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.MicrosoftAntimalwareEngineTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1302 (13.98% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.AspNet.AspNetTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
1269 ( 9.61% of base) : FSharp.Core.dasm - Microsoft.FSharp.Quotations.FSharpExpr:GetLayout(bool):Microsoft.FSharp.Text.StructuredPrintfImpl.Layout:this (FullOpts)
1195 ( 9.25% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateMethods():this (FullOpts)
1135 (14.07% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.Semantics.PredefinedMembers:.cctor() (FullOpts)
1132 (21.54% of base) : System.Private.Xml.dasm - System.Xml.Schema.XdrBuilder:.cctor() (FullOpts)
1093 (12.85% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.Symbols.SynthesizedReadOnlyListTypeSymbol:.ctor(Microsoft.CodeAnalysis.CSharp.Symbols.SourceModuleSymbol,System.String,int,bool):this (FullOpts)
1042 (16.83% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFTimeIntervalFunction():this (FullOpts)
1000 ( 3.33% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.VisualBasic.VisualBasicCommandLineArguments:this (FullOpts)
973 (11.21% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDateTimeFunction():this (FullOpts)
966 (13.44% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:AddToDMTFDateTimeFunction():this (FullOpts)
958 ( 8.91% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeDescription:.cctor() (FullOpts)
951 (17.72% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Etlx.TraceLog:SetupCallbacks(Microsoft.Diagnostics.Tracing.TraceEventDispatcher):this (FullOpts)
905 ( 3.49% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpCommandLineParser:Parse(System.Collections.Generic.IEnumerable`1[System.String],System.String,System.String,System.String):Microsoft.CodeAnalysis.CSharp.CSharpCommandLineArguments:this (FullOpts)
863 (46.80% of base) : System.Management.dasm - System.Management.WmiNetUtilsHelper:LoadPlatformNotSupportedDelegates(System.String) (FullOpts)
846 (14.54% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol:GenerateVarianceDiagnosticsForTypeRecursively(Microsoft.CodeAnalysis.VisualBasic.Symbols.TypeSymbol,short,int,Microsoft.CodeAnalysis.VisualBasic.Symbols.SourceMemberContainerTypeSymbol+VarianceDiagnosticsTargetTypeParameter,int,byref):this (FullOpts)
789 (10.35% of base) : System.Text.RegularExpressions.dasm - System.Text.RegularExpressions.Symbolic.RegexNodeConverter:ConvertToSymbolicRegexNode(System.Text.RegularExpressions.RegexNode):System.Text.RegularExpressions.Symbolic.SymbolicRegexNode`1[System.Text.RegularExpressions.Symbolic.BDD]:this (FullOpts)
786 ( 9.94% of base) : System.Management.dasm - System.Management.ManagementClassGenerator:GenerateProperties():this (FullOpts)
Top method improvements (bytes):
-254 (-1.79% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrDecoder:.cctor() (FullOpts)
-230 (-3.74% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseHelper(System.Text.StringBuilder):this (FullOpts)
-202 (-14.10% of base) : System.Private.Xml.dasm - System.Xml.Schema.XsdBuilder:SetContainer(int,System.Object):this (FullOpts)
-190 (-3.63% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.SignatureDecoder:ParseSignature(int,System.Text.StringBuilder):ILCompiler.Reflection.ReadyToRun.ReadyToRunSignature:this (FullOpts)
-165 (-3.68% of base) : System.Threading.Tasks.Dataflow.dasm - System.Threading.Tasks.Dataflow.TransformManyBlock`2+<StoreOutputItemsNonReorderedWithIterationAsync>d__48[System.__Canon,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-162 (-4.00% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<TakeRangeFromEndIterator>d__194`1[System.Numerics.Vector`1[float]]:MoveNext():this (FullOpts)
-143 (-6.72% of base) : Microsoft.CodeAnalysis.VisualBasic.dasm - Microsoft.CodeAnalysis.VisualBasic.VisualBasicSyntaxNode:DoGetSyntaxErrors(Microsoft.CodeAnalysis.SyntaxTree,Microsoft.CodeAnalysis.SyntaxNodeOrToken):System.Collections.ObjectModel.ReadOnlyCollection`1[Microsoft.CodeAnalysis.Diagnostic] (FullOpts)
-117 (-0.41% of base) : Microsoft.Diagnostics.Tracing.TraceEvent.dasm - Microsoft.Diagnostics.Tracing.Parsers.KernelTraceEventParser:EnumerateTemplates(System.Func`3[System.String,System.String,int],System.Action`1[Microsoft.Diagnostics.Tracing.TraceEvent]):this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.88% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.78% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.86% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[byte,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.87% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[int,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.77% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[long,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.85% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[short,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-116 (-2.68% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[System.Nullable`1[int],System.Nullable`1[int]]:MoveNext():this (FullOpts)
-114 (-5.59% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.CSharpSyntaxTree:BuildPreprocessorStateChangeMap():this (FullOpts)
-112 (-7.76% of base) : System.Data.Common.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.OleDb.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-112 (-7.76% of base) : System.Data.Odbc.dasm - System.Data.Common.DbConnectionOptions:GetKeyValuePair(System.String,int,System.Text.StringBuilder,bool,byref,byref):int (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MaxByAsync>g__Impl|117_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-111 (-2.64% of base) : System.Linq.AsyncEnumerable.dasm - System.Linq.AsyncEnumerable+<<MinByAsync>g__Impl|124_0>d`2[double,System.Nullable`1[int]]:MoveNext():this (FullOpts)
-106 (-10.23% of base) : xunit.runner.utility.netcoreapp10.dasm - Xunit.DelegatingXmlCreationSink:OnMessageWithTypes(Xunit.Abstractions.IMessageSinkMessage,System.Collections.Generic.HashSet`1[System.String]):bool:this (FullOpts)
Top method regressions (percentages):
15 (107.14% of base) : Microsoft.CodeAnalysis.CSharp.dasm - Microsoft.CodeAnalysis.CSharp.LambdaUtilities:IsLambdaBodyStatementOrExpression(Microsoft.CodeAnalysis.SyntaxNode,byref):bool (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetCollapsedTextNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetRootNode(byref):int:this (FullOpts)
12 (100.00% of base) : System.Private.Xml.dasm - System.Xml.XPath.XPathDocument:GetXmlNamespaceNode(byref):int:this (FullOpts)
14 (82.35% of base) : System.Private.Xml.dasm - MS.Internal.Xml.XPath.UnionExpr:ProcessSamePosition(System.Xml.XPath.XPathNavigator):System.Xml.XPath.XPathNavigator:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetParent(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSibling(byref):int:this (FullOpts)
12 (80.00% of base) : System.Private.Xml.dasm - MS.Internal.Xml.Cache.XPathNode:GetSimilarElement(byref):int:this (FullOpts)
15 (78.95% of base) : System.Net.Http.dasm - System.Net.Http.HttpContent:SetHeaders(System.Net.Http.Headers.HttpContentHeaders):this (FullOpts)
15 (78.95% of base) : System.Text.Json.dasm - System.Text.Json.Serialization.Metadata.JsonTypeInfo:SetPolymorphismOptions(System.Text.Json.Serialization.Metadata.JsonPolymorphismOptions):this (FullOpts)
14 (73.68% of base) : Microsoft.CSharp.dasm - Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatchComObject:.ctor(Microsoft.CSharp.RuntimeBinder.ComInterop.IDispatch):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDeclarationWrapper:.ctor(System.Xml.XmlDeclaration):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentTypeWrapper:.ctor(System.Xml.XmlDocumentType):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlDocumentWrapper:.ctor(System.Xml.XmlDocument):this (FullOpts)
14 (73.68% of base) : Newtonsoft.Json.dasm - Newtonsoft.Json.Converters.XmlElementWrapper:.ctor(System.Xml.XmlElement):this (FullOpts)
14 (73.68% of base) : System.IO.Pipelines.dasm - System.IO.Pipelines.BufferSegment:set_NextSegment(System.IO.Pipelines.BufferSegment):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaPinnedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Reflection.MetadataLoadContext.dasm - System.Reflection.TypeLoading.Ecma.EcmaWrappedTypeProvider:.ctor(System.Reflection.TypeLoading.Ecma.EcmaModule):this (FullOpts)
14 (73.68% of base) : System.Speech.dasm - System.Speech.Internal.SrgsCompiler.State:Add(System.Speech.Internal.SrgsCompiler.State):System.Speech.Internal.SrgsCompiler.State:this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[byte]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[byte]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[int]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[int]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[long]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[long]):this (FullOpts)
14 (73.68% of base) : System.Threading.Tasks.Parallel.dasm - System.Threading.Tasks.ParallelLoopState`1[short]:.ctor(System.Threading.Tasks.ParallelLoopStateFlags`1[short]):this (FullOpts)
14 (73.68% of base) : System.Private.Xml.dasm - System.Xml.ValidatingReaderNodeData:SetItemData(System.String):this (FullOpts)
Top method improvements (percentages):
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.NativeVarInfo:set_Variable(ILCompiler.Reflection.ReadyToRun.Variable):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection:set_Entries(System.Collections.Generic.List`1[ILCompiler.Reflection.ReadyToRun.ReadyToRunImportSection+ImportSectionEntry]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.ReadyToRunReader+DecodedMethodSignature:set_OwningType(System.String):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.WebcilImageReader+WasmFunctionInfo:set_Locals(System.Collections.Generic.IReadOnlyList`1[System.ValueTuple`2[uint,byte]]):this (FullOpts)
-4 (-40.00% of base) : ILCompiler.Reflection.ReadyToRun.dasm - ILCompiler.Reflection.ReadyToRun.x86.InfoHdrSmall:set_Epilogs(System.Collections.Generic.List`1[int]):this (FullOpts)
-4 (-40.00% of base) : System.Private.CoreLib.dasm - Internal.Runtime.InteropServices.ComActivator+BasicClassFactory+ValidatedInterfaceType:set_ManagedType(System.Type):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.AttributeUsageInfo+ValidTargetsStringLocalizableErrorArgument:.ctor(System.String[]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.CodeAnalysisResourcesLocalizableErrorArgument:.ctor(System.String):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+KeyCollection[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[long,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[long,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[short,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[short,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Nullable`1[int],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Nullable`1[int],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+TestAccessor[System.Numerics.Vector`1[float],System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[System.Numerics.Vector`1[float],System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[byte,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[byte,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[double,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[double,System.Nullable`1[int]]):this (FullOpts)
-4 (-40.00% of base) : Microsoft.CodeAnalysis.dasm - Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder+ValueCollection[int,System.Nullable`1[int]]:.ctor(Microsoft.CodeAnalysis.Collections.ImmutableSegmentedDictionary`2+Builder[int,System.Nullable`1[int]]):this (FullOpts)
106592 total methods with Code Size differences (10237 improved, 96355 regressed), 374498 unchanged.
--------------------------------------------------------------------------------

cc @jkotas @dotnet/jit-contrib I am not sure what that is telling us for x64/arm64 whether we want to do that for those

@EgorBoEgorBo closed this May 30, 2026
@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

Example codegen regression

Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this

 ; Assembly listing for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)
; Emitting BLENDED_CODE for x86 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; esp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 2 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
-; V00 this [V00,T00] ( 4, 4 ) ref -> ecx this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>-; V01 arg1 [V01,T01] ( 4, 4 ) ref -> eax class-hnd single-def <System.Xml.Linq.XDocumentType>+; V00 this [V00,T00] ( 4, 4 ) ref -> [esp+0x00] this class-hnd single-def <Newtonsoft.Json.Converters.XDocumentTypeWrapper>+; V01 arg1 [V01,T01] ( 4, 4 ) ref -> esi class-hnd single-def <System.Xml.Linq.XDocumentType>
;
-; Lcl frame size = 0+; Lcl frame size = 4
G_M23744_IG01:
- mov eax, edx- ;; size=2 bbWeight=1 PerfScore 0.25+ push esi+ push eax+ mov esi, edx+ ;; size=4 bbWeight=1 PerfScore 2.25
G_M23744_IG02:
- lea edx, bword ptr [ecx+0x04]- call CORINFO_HELP_ASSIGN_REF_EAX- lea edx, bword ptr [ecx+0x08]- call CORINFO_HELP_ASSIGN_REF_EAX- ;; size=16 bbWeight=1 PerfScore 3.00+ mov gword ptr [esp], ecx+ lea ecx, bword ptr [ecx+0x04]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ mov ecx, gword ptr [esp]+ lea ecx, bword ptr [ecx+0x08]+ mov edx, esi+ call CORINFO_HELP_ASSIGN_REF+ ;; size=26 bbWeight=1 PerfScore 5.50
G_M23744_IG03:
+ pop ecx+ pop esi
ret
- ;; size=1 bbWeight=1 PerfScore 1.00+ ;; size=3 bbWeight=1 PerfScore 2.00-; Total bytes of code 19, prolog size 0, PerfScore 4.25, instruction count 6, allocated bytes for code 19 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)+; Total bytes of code 33, prolog size 2, PerfScore 9.75, instruction count 14, allocated bytes for code 35 (MethodHash=0332a33f) for method Newtonsoft.Json.Converters.XDocumentTypeWrapper:.ctor(System.Xml.Linq.XDocumentType):this (FullOpts)

Summary

base (main)diff (PR)delta
Code size (bytes)1933+14 (+73.7%)
Instruction count614+8
PerfScore4.259.75+5.50

Why it regressed

  • Baseline (per-reg WB): this stays in ECX (callee-saved across ASSIGN_REF_EAX); arg1 moves to EAX once; two short call CORINFO_HELP_ASSIGN_REF_EAX.
  • Diff (unified WB): this can't stay in ECX because ECX is now the dst arg, andarg1 can't stay in EAX because EAX is now in the WB kill set. LSRA spills this to the stack ([esp+0x00]) and parks arg1 in callee-saved ESI. Each store needs to reload this from stack into ECX, LEA the field address, copy ESI→EDX, and call — plus prolog push esi/eax and epilog pop ecx/esi.

@EgorBo

EgorBo commented May 30, 2026

Copy link
Copy Markdown
MemberAuthor

I wonder if it's mostly just the typical this (ECX) is the issue so we can change the write barrier to never touch ECX despite it being caller-saved. Same idea for x64

@EgorBo

Copy link
Copy Markdown
MemberAuthor

I've modified the JIT to assume that whatever CC this register is not changed (and is not used to pass parameters) and got -1,339,638 diff on win-x64 (optimized code only)

@github-actionsgithub-actionsBot locked and limited conversation to collaborators Jun 30, 2026
Sign up for freeto subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

area-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants

@EgorBo@jakobbotsch