Skip to content

Prototype changes for TYP_HALF with refactored vartypes.#16

Closed
anthonycanino wants to merge 1 commit into
simd-vartypesfrom
half-vartypes
Closed

Prototype changes for TYP_HALF with refactored vartypes.#16
anthonycanino wants to merge 1 commit into
simd-vartypesfrom
half-vartypes

Conversation

@anthonycanino

Copy link
Copy Markdown
Owner

Consider the following C# snippet

public static Half ProduceHalf(float val, float val2)
{
	Half h1 = (Half)val;
	Half h2 = (Half)val2;
	return ConsumeHalf(h1, h2);
}

public static Half ConsumeHalf(Half h1, Half h2)
{
	Half h3 = h1 + h2;
	return h3;
}

My changes produce the following Tier0 code...

; Assembly listing for method Program:ProduceHalf(float,float):System.Half (Tier0)
; Emitting BLENDED_CODE for generic X64 + VEX + EVEX on Windows
; Tier0 code
; rbp based frame
; partially interruptible
; compiling with minopt
; invoked as altjit
; Final local variable assignments
;
;  V00 arg0         [V00    ] (  1,  1   )   float  ->  [rbp+0x10]  do-not-enreg[]
;  V01 arg1         [V01    ] (  1,  1   )   float  ->  [rbp+0x18]  do-not-enreg[]
;  V02 loc0         [V02    ] (  1,  1   )    half  ->  [rbp-0x08]  do-not-enreg[S] must-init <System.Half>
;  V03 OutArgs      [V03    ] (  1,  1   )  struct (32) [rsp+0x00]  do-not-enreg[XS] addr-exposed "OutgoingArgSpace" <UNNAMED>
;  V04 tmp1         [V04    ] (  1,  1   )    half  ->  [rbp-0x10]  do-not-enreg[S] "non-inline candidate call"
;
; Lcl frame size = 48

G_M43922_IG01:  ;; offset=0x0000
       55                   push     rbp
       4883EC30             sub      rsp, 48
       488D6C2430           lea      rbp, [rsp+0x30]
       33C0                 xor      eax, eax
       488945F8             mov      qword ptr [rbp-0x08], rax
       C5FA114510           vmovss   dword ptr [rbp+0x10], xmm0
       C5FA114D18           vmovss   dword ptr [rbp+0x18], xmm1
						;; size=26 bbWeight=1 PerfScore 5.00
G_M43922_IG02:  ;; offset=0x001A
       C5FA104510           vmovss   xmm0, dword ptr [rbp+0x10]
       FF1593BB7E00         call     [System.Half:op_Explicit(float):System.Half]
       668945F0             mov      word  ptr [rbp-0x10], ax
       C5FA104518           vmovss   xmm0, dword ptr [rbp+0x18]
       FF1584BB7E00         call     [System.Half:op_Explicit(float):System.Half]
       668945F8             mov      word  ptr [rbp-0x08], ax
       0FB74DF0             movzx    rcx, word  ptr [rbp-0x10]
       0FB755F8             movzx    rdx, word  ptr [rbp-0x08]
       FF158ABB7E00         call     [Program:ConsumeHalf(System.Half,System.Half):System.Half]
       90                   nop      
						;; size=45 bbWeight=1 PerfScore 19.25
G_M43922_IG03:  ;; offset=0x0047
       4883C430             add      rsp, 48
       5D                   pop      rbp
       C3                   ret      
						;; size=6 bbWeight=1 PerfScore 1.75

; Total bytes of code 77, prolog size 16, PerfScore 26.00, instruction count 20, allocated bytes for code 77 (MethodHash=f2a4546d) for method Program:ProduceHalf(float,float):System.Half (Tier0)
; ============================================================

; Assembly listing for method Program:ConsumeHalf(System.Half,System.Half):System.Half (Tier0)
; Emitting BLENDED_CODE for generic X64 + VEX + EVEX on Windows
; Tier0 code
; rbp based frame
; partially interruptible
; compiling with minopt
; invoked as altjit
; Final local variable assignments
;
;  V00 arg0         [V00    ] (  1,  1   )    half  ->  [rbp+0x10]  do-not-enreg[S] <System.Half>
;  V01 arg1         [V01    ] (  1,  1   )    half  ->  [rbp+0x18]  do-not-enreg[S] <System.Half>
;  V02 OutArgs      [V02    ] (  1,  1   )  struct (32) [rsp+0x00]  do-not-enreg[XS] addr-exposed "OutgoingArgSpace" <UNNAMED>
;
; Lcl frame size = 32

G_M44932_IG01:  ;; offset=0x0000
       55                   push     rbp
       4883EC20             sub      rsp, 32
       488D6C2420           lea      rbp, [rsp+0x20]
       894D10               mov      dword ptr [rbp+0x10], ecx
       895518               mov      dword ptr [rbp+0x18], edx
						;; size=16 bbWeight=1 PerfScore 3.75
G_M44932_IG02:  ;; offset=0x0010
       0FB74D10             movzx    rcx, word  ptr [rbp+0x10]
       0FB75518             movzx    rdx, word  ptr [rbp+0x18]
       FF15EABA7E00         call     [System.Half:op_Addition(System.Half,System.Half):System.Half]
       90                   nop      
						;; size=15 bbWeight=1 PerfScore 5.25
G_M44932_IG03:  ;; offset=0x001F
       4883C420             add      rsp, 32
       5D                   pop      rbp
       C3                   ret      
						;; size=6 bbWeight=1 PerfScore 1.75

; Total bytes of code 37, prolog size 10, PerfScore 10.75, instruction count 12, allocated bytes for code 37 (MethodHash=5608507b) for method Program:ConsumeHalf(System.Half,System.Half):System.Half (Tier0)
; ============================================================

and the following Tier1 code

; Assembly listing for method Program:ProduceHalf(float,float):System.Half (FullOpts)
; Emitting BLENDED_CODE for generic X64 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; invoked as altjit
; Final local variable assignments
;
;  V00 arg0         [V00,T00] (  3,  3   )   float  ->  mm0         single-def
;  V01 arg1         [V01,T01] (  3,  3   )   float  ->  mm1         single-def
;  V02 loc0         [V02    ] (  2,  2   )    half  ->  [rsp+0x20]  single-def <System.Half>
;  V03 OutArgs      [V03    ] (  1,  1   )  struct (32) [rsp+0x00]  do-not-enreg[XS] addr-exposed "OutgoingArgSpace" <UNNAMED>
;
; Lcl frame size = 40

G_M43922_IG01:  ;; offset=0x0000
       4883EC28             sub      rsp, 40
						;; size=4 bbWeight=1 PerfScore 0.25
G_M43922_IG02:  ;; offset=0x0004
       62F574081DC9         vcvtss2sh xmm1, xmm1
       62F57E08114C2410     vmovsh   word  ptr [rsp+0x20], xmm1
       62F57C081DC0         vcvtss2sh xmm0, xmm0
       C5F97EC1             vmovd    ecx, xmm0
       0FB7542420           movzx    rdx, word  ptr [rsp+0x20]
       FF15D1BB7E00         call     [Program:ConsumeHalf(System.Half,System.Half):System.Half]
       90                   nop      
						;; size=36 bbWeight=1 PerfScore 9.25
G_M43922_IG03:  ;; offset=0x0028
       4883C428             add      rsp, 40
       C3                   ret      
						;; size=5 bbWeight=1 PerfScore 1.25

; Total bytes of code 45, prolog size 4, PerfScore 10.75, instruction count 10, allocated bytes for code 45 (MethodHash=f2a4546d) for method Program:ProduceHalf(float,float):System.Half (FullOpts)
; ============================================================

; Assembly listing for method Program:ConsumeHalf(System.Half,System.Half):System.Half (FullOpts)
; Emitting BLENDED_CODE for generic X64 + VEX + EVEX on Windows
; FullOpts code
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; invoked as altjit
; Final local variable assignments
;
;  V00 arg0         [V00    ] (  3,  3   )    half  ->  [rsp+0x08]  single-def <System.Half>
;  V01 arg1         [V01    ] (  3,  3   )    half  ->  [rsp+0x10]  single-def <System.Half>
;# V02 OutArgs      [V02    ] (  1,  1   )  struct ( 0) [rsp+0x00]  do-not-enreg[XS] addr-exposed "OutgoingArgSpace" <Empty>
;
; Lcl frame size = 0

G_M44932_IG01:  ;; offset=0x0000
       66894C2408           mov      word  ptr [rsp+0x08], cx
       6689542410           mov      word  ptr [rsp+0x10], dx
						;; size=10 bbWeight=1 PerfScore 2.00
G_M44932_IG02:  ;; offset=0x000A
       62F57E0810442404     vmovsh   xmm0, word  ptr [rsp+0x08]
       62F57E0858442408     vaddsh   xmm0, xmm0, word  ptr [rsp+0x10]
       C5F97EC0             vmovd    eax, xmm0
						;; size=20 bbWeight=1 PerfScore 6.00
G_M44932_IG03:  ;; offset=0x001E
       C3                   ret      
						;; size=1 bbWeight=1 PerfScore 1.00

; Total bytes of code 31, prolog size 0, PerfScore 9.00, instruction count 6, allocated bytes for code 31 (MethodHash=5608507b) for method Program:ConsumeHalf(System.Half,System.Half):System.Half (FullOpts)
; ============================================================

@anthonycanino

anthonycanino commented Nov 12, 2025

Copy link
Copy Markdown
Owner Author

For the unoptimized ConsumeHalf, prior to lowering my tree looks like this...

STMT00000 ( 0x000[E-] ... 0x007 )
N004 (???,???) [000003] --CXG+-----                         *  RETURN    half  
N003 (???,???) [000002] --CXG+-----                         \--*  CALL      half   System.Half:op_Addition(System.Half,System.Half):System.Half
N001 (???,???) [000000] -----+----- arg0 rcx                   +--*  LCL_VAR   half  <System.Half, 2> V00 arg0         
N002 (???,???) [000001] -----+----- arg1 rdx                   \--*  LCL_VAR   half  <System.Half, 2> V01 arg1  

after lowering look like this...

              [000004] -----------                            IL_OFFSET void   INLRT @ 0x000[E-]
N001 (???,???) [000000] -c---+-----                    t0 =    LCL_VAR   half  <System.Half, 2> V00 arg0         
                                                            /--*  t0     half   
               [000005] -----------                    t5 = *  BITCAST   ushort
                                                            /--*  t5     ushort 
               [000006] -----------                    t6 = *  PUTARG_REG int    REG rcx
N002 (???,???) [000001] -c---+-----                    t1 =    LCL_VAR   half  <System.Half, 2> V01 arg1         
                                                            /--*  t1     half   
               [000007] -----------                    t7 = *  BITCAST   ushort
                                                            /--*  t7     ushort 
               [000008] -----------                    t8 = *  PUTARG_REG int    REG rdx
N001 (???,???) [000009] Hc---------                    t9 =    CNS_INT(h) long   0x7ffd85f27b58 ftn
                                                            /--*  t9     long   
N002 (???,???) [000010] nc--G------                   t10 = *  IND       long   REG NA
                                                            /--*  t6     int    arg0 rcx
                                                            +--*  t8     int    arg1 rdx
                                                            +--*  t10    long   control expr
N003 (???,???) [000002] --CXG+-----                    t2 = *  CALL      int    System.Half:op_Addition(System.Half,System.Half):System.Half
                                                            /--*  t2     int    
N004 (???,???) [000003] --CXG+-----                         *  RETURN    int 

For the optimized ConsumeHalf, prior to lowering my tree looks like this...

               [000004] -----------                            IL_OFFSET void   INLRT @ 0x000[E-]
N001 (  1,  2) [000000] -----+-----                    t0 =    LCL_VAR   half  <System.Half, 2> V00 arg0          $c0
N002 (  1,  2) [000001] -----+-----                    t1 =    LCL_VAR   half  <System.Half, 2> V01 arg1          $c1
                                                            /--*  t0     half   
                                                            +--*  t1     half   
N003 (  3,  5) [000002] -----+-----                    t2 = *  HWINTRINSIC half   16 half HalfAdd $140
                                                            /--*  t2     half   
N004 (  4,  6) [000003] -----+-----                         *  RETURN    half   $VN.Void

after lowering look like this...

               [000004] -----------                            IL_OFFSET void   INLRT @ 0x000[E-]
N001 (  1,  2) [000000] -----+-----                    t0 =    LCL_VAR   half  <System.Half, 2> V00 arg0          $c0
N002 (  1,  2) [000001] -----+-----                    t1 =    LCL_VAR   half  <System.Half, 2> V01 arg1          $c1
                                                            /--*  t0     half   
                                                            +--*  t1     half   
N003 (  3,  5) [000002] -----+-----                    t2 = *  HWINTRINSIC half   16 half HalfAdd $140
                                                            /--*  t2     half   
               [000005] -----------                    t5 = *  BITCAST   int   
                                                            /--*  t5     int    
N004 (  4,  6) [000003] -----+-----                         *  RETURN    int    $VN.Void

We can see the ABI respected when the half type needs to passed, but when it does not, it is treated as a float register.

I like how the trees look a bit more now, but I have disabled some asserts, particular, we are allowing a BITCAST from half to ushort and allowing the ushort to be placed with a PUTREG.

For reference, here are the full jit dumps are attached.

half-unopt.txt
haf-opt.txt

Comment on lines +2990 to 3004
instruction store_ins = ins_Store(storeType);
if (storeType == TYP_HALF)
{
// We cannot use `vmovsh` with an integer register, which is what the ABI would pass the
// 16-bit float value in. Switch to `vmov` which supports integer registers.
#if defined(TARGET_XARCH)
store_ins = INS_mov;
#else
store_ins = INS_invalid;
assert(!"TYP_HALF parameter passing not supported on this platform");
#endif
}

GetEmitter()->emitIns_S_R(store_ins, emitActualTypeSize(storeType), segment.GetRegister(), lclNum,
offset);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I get this, but it also seems like "extra work" that might pessimize the typical path.

I wonder if it'd be better to just keep TYP_STRUCT, much as it is for the struct S { float value; } case. In which case the classifier would state it lives in a GPR and we'd just get INS_mov already. I wouldn't expect us to track it as TYP_HALF unless we're

So we'd only retype/normalize to TYP_HALF in the case the ABI is being followed and its passed in SIMD register (at which point we can use vpextrw and vpinsrw/vmovd (F16C) or vmovw (AVX512-FP16)

This might even push us in the direction that following the ABI is trivial and expected. We only produce TYP_HALF if its accelerated and the handling in that case is correct by convention of it being floating-point and following the other floating-point conventions.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Hmm, I am not sure I completely follow.

Would we then perform a normalization/type conversion as a separate compiler pass? Meaning, we do not normalize on a struct import like it is currently done?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I'm wondering if the idea to preserve the existing behavior is actually making this more complex, rather than simpler. I'm thinking it's actually less work to just do this right in the first place, ABI wise.

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

From what I've seen, I think it is.

One thing I can try is prototyping the ABI where half is passed and returned in a float register. We can see if it is much simpler. That shouldn't take too long to try out.

@anthonycanino anthonycanino Nov 17, 2025

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

@tannergooding I put the changes on a separate branch #17

I have not addressed all nits below, but I wanted to get the major changes up and see what the code looked like. I think this is much easier I am only changing a few places. You'll see in the code that some of the signature checking might need to be updated. It's much easier to not treat TYP_HALF as a struct in any way, and instead treat it wholly as a primitive type (otherwise the jit picks it up as a struct in so many places where different handling is needed).

@anthonycanino anthonycanino Dec 10, 2025

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

I did it intensionally

When TYP_HALF was treated as a struct type, it caused a lot handling to apply to the type that didn't make sense for a primitive type.

One confusion that is going on, and perhaps we should move the conversation, is that we are talking about the PR at #17, where I redid the handling of the half type to more closely match that of a primitive float type in terms of the ABI.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

There's a difference between treating it as TYP_STRUCT and having it classified as a struct such that varTypeIsStruct(...) report true (being marked with VTF_S).

We don't expect the former, because we're retyping it to TYP_HALF (much as we retype to TYP_SIMD8/12/16/32/64). But we do still expect the latter.

Looking at the new type entry, it may be that the combination of VTF_S and VTF_FLT is breaking things here, as that may get into ordering or other nuance that hasn't been accounted for due to it being a "new combination". So I'd suggest removing VTF_FLT for now and just having it be specially handled via the intrinsic code paths. We can always look at also handling VTF_FLT in the future if that provides benefit

-- This basically means varTypeIsFloating(...) will report false, but that's probably okay if we're importing everything as GT_HWINTRINSIC nodes anyways. We'd really only need the other if we end up making scalar support more "first class" such that GT_ADD and such works.

@anthonycanino anthonycanino Dec 10, 2025

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

I had tried that route previously, and there are a lot of asserts that get hit. For example, in the gtNewSimdToScalarNode which we use to build up the Half operations, this will trigger...

image

likewise, I believe there are a lot of places where when generating the code or hwintrisic, varTypeIsFloating is checked, for example...

image

I don't think these are isolated to the one Vector128_ToScalar case, but I can try adding an or case there to see.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Right, I expect there will be several fixups regardless of including it or not.

I expect that its inclusion is what’s making the “invalid IR” right now.

You could (if keeping the flag) try to find and handle those cases, such as by ensuring varTypeIsStruct comes first, so it takes precedence over varTypeIsFloating, or (if you remove the flag) you could update the hardware intrinsic paths to also allow TYP_HALF in may of the paths that assert it must be floating-point

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

It’s really just an area where we’ve not quite done “this” before and so we don’t have things in place to make it easy.

We’d have the same general issues with adding some TYP_INT128. Anything added after this pr should be much easier, however

void CodeGen::genCodeForBitCast(GenTreeOp* treeNode)
{
assert(treeNode->TypeGet() == genActualType(treeNode));
//assert(treeNode->TypeGet() == genActualType(treeNode));

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Why does this need commented out? I'd expect in this to just be TYP_HALF == TYP_HALF since we aren't implicitly extending the type up to a larger type size

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

You can see this in the trees above, but what happens is Lowering::InsertBitCastIfNecessary will insert the bitcast to TYP_USHORT not TYP_HALF, as the ABI defines the TYP_HALF to be passed in an integer register. The code will grab the appropriate integer register for a 2 byte value, hence, TYP_USHORT.

https://github.com/dotnet/runtime/blob/main/src/coreclr/jit/lower.cpp#L1934-L1944

It's this line in particular that will produce the bitcast...

https://github.com/dotnet/runtime/blob/main/src/coreclr/jit/lower.cpp#L1923

TYP_HALF has to be defined to use float registers, but its ABI register segement info defines it to require integer register for passing.

Comment on lines +3080 to +3081
assert((leadingBytes == 0x0F) || ((emitComp->compIsaSupportedDebugOnly(InstructionSet_AVX10v1) ||
emitComp->compIsaSupportedDebugOnly(InstructionSet_AVX10v2) ||

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

This can just check 10v1 as it implies 10v2

else if (code & 0xFF000000)
{
if (size == EA_2BYTE)
if (size == EA_2BYTE && ins != INS_vmovsh)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Checking if its a vex/evex/simd instruction might be more appropriate, since those all shouldn't be EA_2BYTE or should have this prefix byte as part of their better encoding.

else if (code & 0xFF000000)
{
if (size == EA_2BYTE)
if (size == EA_2BYTE && (ins != INS_vmovsh && ins != INS_vaddsh))

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Similar comment here and elsewhere

break;
}

case NI_AVX10v1_ConvertFloatToHalf:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

nit: ConvertSingleToHalf


// Don't bother if the struct contains GC references of byrefs, it can't be a SIMD type.
if ((structFlags & (CORINFO_FLG_CONTAINS_GC_PTR | CORINFO_FLG_BYREF_LIKE)) == 0)
if ((structFlags & (CORINFO_FLG_CONTAINS_GC_PTR | CORINFO_FLG_BYREF_LIKE)) == 0 && (structFlags & CORINFO_FLG_INTRINSIC_TYPE) != 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I think this can be simplified to (structFlags & (CORINFO_FLG_CONTAINS_GC_PTR | CORINFO_FLG_BYREF_LIKE | CORINFO_FLG_INTRINSIC_TYPE)) == CORINFO_FLG_INTRINSIC_TYPE

Comment thread src/coreclr/jit/simd.cpp
}
}
}
else if (strcmp(namespaceName, "System") == 0)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Not sure this is the "right" place for this, particularly given the current method name.

anthonycanino pushed a commit that referenced this pull request Dec 18, 2025
Enable X64's optimization where we clear LCLHEAP via STORE_BLK inserted
in Lower on arm64.

```cs
static void Test128() => Consume(stackalloc char[128]);
```
was:
```asm
            stp     xzr, xzr, [sp, #-0x10]!
            stp     xzr, xzr, [sp, #-0xF0]!
            stp     xzr, xzr, [sp, #0x10]
            stp     xzr, xzr, [sp, #0x20]
            stp     xzr, xzr, [sp, #0x30]
            stp     xzr, xzr, [sp, #0x40]
            stp     xzr, xzr, [sp, #0x50]
            stp     xzr, xzr, [sp, #0x60]
            stp     xzr, xzr, [sp, #0x70]
            stp     xzr, xzr, [sp, #0x80]
            stp     xzr, xzr, [sp, #0x90]
            stp     xzr, xzr, [sp, #0xA0]
            stp     xzr, xzr, [sp, #0xB0]
            stp     xzr, xzr, [sp, #0xC0]
            stp     xzr, xzr, [sp, #0xD0]
            stp     xzr, xzr, [sp, #0xE0]
```
now:
```asm
            movi    v16.16b, #0
            stp     q16, q16, [x0]
            stp     q16, q16, [x0, #0x20]
            stp     q16, q16, [x0, #0x40]
            stp     q16, q16, [x0, #0x60]
            stp     q16, q16, [x0, #0x80]
            stp     q16, q16, [x0, #0xA0]
            stp     q16, q16, [x0, #0xC0]
            stp     q16, q16, [x0, #0xE0]
```

Also, for larger sizes the previous logic used to emit a slow loop (e.g.
1024 bytes):
```asm
            mov     w0, #0x400
G_M30953_IG03:
            stp     xzr, xzr, [sp, #-0x10]!
            subs    x0, x0, #16
            bne     G_M30953_IG03
```
Now it will emit a call to `CORINFO_HELP_MEMZERO`


[Benchmarks.](EgorBot/runtime-utils#553)

```cs
using System.Runtime.CompilerServices;
using BenchmarkDotNet.Attributes;

public class Benchmarks
{
    [Benchmark] public void Stackalloc64() => Consume(stackalloc byte[64]);
    [Benchmark] public void Stackalloc128() => Consume(stackalloc byte[128]);
    [Benchmark] public void Stackalloc256() => Consume(stackalloc byte[256]);
    [Benchmark] public void Stackalloc512() => Consume(stackalloc byte[512]);
    [Benchmark] public void Stackalloc1024() => Consume(stackalloc byte[1024]);
    [Benchmark] public void Stackalloc16384() => Consume(stackalloc byte[16384]);

    [MethodImpl(MethodImplOptions.NoInlining)]
    static void Consume(Span<byte> x){}
}
```

| Method | Toolchain | Mean | Error | Ratio |
|---------------- |------------------------
|-----------:|----------:|------:|
| Stackalloc64    | Main |   3.425 ns | 0.0004 ns |  1.00 |
| Stackalloc64    | PR |   2.559 ns | 0.0008 ns |  0.75 |
| | | | | |
| Stackalloc128   | Main |   3.999 ns | 0.0002 ns |  1.00 |
| Stackalloc128   | PR |   2.404 ns | 0.0003 ns |  0.60 |
| | | | | |
| Stackalloc256   | Main |   5.431 ns | 0.0005 ns |  1.00 |
| Stackalloc256   | PR |   2.754 ns | 0.0003 ns |  0.51 |
| | | | | |
| Stackalloc512   | Main |  12.661 ns | 0.2744 ns |  1.00 |
| Stackalloc512   | PR |   7.423 ns | 0.0008 ns |  0.59 |
| | | | | |
| Stackalloc1024  | Main |  24.958 ns | 0.5326 ns |  1.00 |
| Stackalloc1024  | PR |  14.031 ns | 0.0040 ns |  0.56 |
| | | | | |
| Stackalloc16384 | Main | 374.899 ns | 0.0130 ns |  1.00 |
| Stackalloc16384 | PR | 111.029 ns | 1.2123 ns |  0.30 |

---------

Co-authored-by: Jakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
tannergooding pushed a commit that referenced this pull request Apr 15, 2026
i.e. Fold: (-(x)) == 0  ->  x == 0

arm64 asmdiffs
Diffs are based on <span style="color:#1460aa">436,095</span> contexts
(<span style="color:#1460aa">26,618</span> MinOpts, <span
style="color:#1460aa">409,477</span> FullOpts).


<details>
<summary>Overall (<span style="color:green">-40</span> bytes)</summary>
<div style="margin-left:1em">

|Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs
|---|--:|--:|--:|

|libraries_tests_no_tiered_compilation.run.linux.arm64.Release.mch|183,146,276|<span
style="color:green">-40</span>|<span style="color:green">-0.09%</span>|
|benchmarks.run.linux.arm64.checked.mch|21,285,888|+0|0.00%|
|smoke_tests.nativeaot.linux.arm64.checked.mch|3,003,400|+0|0.00%|


</div></details>

<details>
<summary>FullOpts (<span style="color:green">-40</span> bytes)</summary>
<div style="margin-left:1em">

|Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs
|---|--:|--:|--:|

|libraries_tests_no_tiered_compilation.run.linux.arm64.Release.mch|168,630,412|<span
style="color:green">-40</span>|<span style="color:green">-0.09%</span>|
|benchmarks.run.linux.arm64.checked.mch|20,953,436|+0|0.00%|
|smoke_tests.nativeaot.linux.arm64.checked.mch|3,001,776|+0|0.00%|


</div></details>

<details>
<summary>Example diffs</summary>
<div style="margin-left:1em">


<details>

<summary>libraries_tests_no_tiered_compilation.run.linux.arm64.Release.mch</summary>
<div style="margin-left:1em">


<details>
<summary><span style="color:green">-4</span> (<span
style="color:green">-1.27%</span>) : 142473.dasm -
System.IO.Pipelines.Tests.BufferSegmentPoolTest:GetSegments(System.IO.Pipelines.ReadResult):System.Collections.Generic.List`1[System.Buffers.ReadOnlySequenceSegment`1[byte]]
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -53,8 +53,7 @@ G_M13215_IG02:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0001 {x0}, byre
 G_M13215_IG03:        ; bbWeight=0.50, gcrefRegs=80002 {x1 x19}, byrefRegs=0000 {}, byref, isz
             asr     w2, w2, dotnet#31
             lsl     w2, w2, #1
-            add     w0, w2, w0,  ASR dotnet#31
-            negs    w0, w0
+            adds    w0, w2, w0,  ASR dotnet#31
             bne     G_M13215_IG04
             movz    x0, #0xD1FFAB1E
             movk    x0, #0xD1FFAB1E LSL #16
@@ -76,7 +75,7 @@ G_M13215_IG03:        ; bbWeight=0.50, gcrefRegs=80002 {x1 x19}, byrefRegs=0000
             mov     x19, x0
             ; gcrRegs +[x19]
             b       G_M13215_IG05
-						;; size=68 bbWeight=0.50 PerfScore 6.00
+						;; size=64 bbWeight=0.50 PerfScore 5.75
 G_M13215_IG04:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
             ; gcrRegs -[x0 x19-x20]
             mov     x20, xzr
@@ -179,7 +178,7 @@ G_M13215_IG13:        ; bbWeight=0, gcrefRegs=580000 {x19 x20 x22}, byrefRegs=00
             b       G_M13215_IG06
 						;; size=12 bbWeight=0 PerfScore 0.00
 
-; Total bytes of code 316, prolog size 16, PerfScore 140.93, instruction count 79, allocated bytes for code 316 (MethodHash=c6bccc60) for method System.IO.Pipelines.Tests.BufferSegmentPoolTest:GetSegments(System.IO.Pipelines.ReadResult):System.Collections.Generic.List`1[System.Buffers.ReadOnlySequenceSegment`1[byte]] (FullOpts)
+; Total bytes of code 312, prolog size 16, PerfScore 140.68, instruction count 78, allocated bytes for code 312 (MethodHash=c6bccc60) for method System.IO.Pipelines.Tests.BufferSegmentPoolTest:GetSegments(System.IO.Pipelines.ReadResult):System.Collections.Generic.List`1[System.Buffers.ReadOnlySequenceSegment`1[byte]] (FullOpts)
 ; ============================================================
 
 Unwind Info:
@@ -190,7 +189,7 @@ Unwind Info:
   E bit             : 0
   X bit             : 0
   Vers              : 0
-  Function Length   : 79 (0x0004f) Actual length = 316 (0x00013c)
+  Function Length   : 78 (0x0004e) Actual length = 312 (0x000138)
   ---- Epilog scopes ----
   ---- Scope 0
   Epilog Start Offset        : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
```

</div></details>

<details>
<summary><span style="color:green">-4</span> (<span
style="color:green">-0.27%</span>) : 162917.dasm -
System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory():this
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -531,10 +531,9 @@ G_M17523_IG25:        ; bbWeight=1, gcrefRegs=400002 {x1 x22}, byrefRegs=0000 {}
 G_M17523_IG26:        ; bbWeight=0.50, gcrefRegs=80002 {x1 x19}, byrefRegs=0000 {}, byref, isz
             asr     w0, w0, dotnet#31
             lsl     w0, w0, #1
-            add     w0, w0, w2,  ASR dotnet#31
-            negs    w0, w0
+            adds    w0, w0, w2,  ASR dotnet#31
             beq     G_M17523_IG29
-						;; size=20 bbWeight=0.50 PerfScore 2.25
+						;; size=16 bbWeight=0.50 PerfScore 2.00
 G_M17523_IG27:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
             ; gcrRegs -[x1 x19]
             mov     w19, wzr
@@ -733,7 +732,7 @@ G_M17523_IG43:        ; bbWeight=0.00, gcrefRegs=0001 {x0}, byrefRegs=0000 {}, b
             brk     #0
 						;; size=32 bbWeight=0.00 PerfScore 0.00
 
-; Total bytes of code 1488, prolog size 36, PerfScore 200.96, instruction count 372, allocated bytes for code 1488 (MethodHash=abb9bb8c) for method System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory():this (FullOpts)
+; Total bytes of code 1484, prolog size 36, PerfScore 200.71, instruction count 371, allocated bytes for code 1484 (MethodHash=abb9bb8c) for method System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory():this (FullOpts)
 ; ============================================================
 
 Unwind Info:
@@ -744,7 +743,7 @@ Unwind Info:
   E bit             : 0
   X bit             : 0
   Vers              : 0
-  Function Length   : 372 (0x00174) Actual length = 1488 (0x0005d0)
+  Function Length   : 371 (0x00173) Actual length = 1484 (0x0005cc)
   ---- Epilog scopes ----
   ---- Scope 0
   Epilog Start Offset        : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
```

</div></details>

<details>
<summary><span style="color:green">-4</span> (<span
style="color:green">-0.26%</span>) : 162915.dasm -
System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory_String():this
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -208,7 +208,7 @@
 ;  V197 cse1        [V197,T40] (  2,  1   )     ref  ->   x0         "CSE #7: moderate"
 ;  V198 cse2        [V198,T44] (  2,  1   )     int  ->  x23         "CSE #4: moderate"
 ;  V199 cse3        [V199,T45] (  2,  1   )    long  ->   x1         "CSE #5: moderate"
-;  V200 cse4        [V200,T33] (  3,  1.50)     int  ->   x1         "CSE #17: moderate"
+;  V200 cse4        [V200,T33] (  3,  1.50)     int  ->   x1         "CSE #16: moderate"
 ;  V201 rat0        [V201,T01] (  3,  5.62)   byref  ->   x1         "fgMakeTemp is creating a new local variable"
 ;  V202 rat1        [V202,T07] (  5,  3.75)     ref  ->   x0         "replacement local"
 ;  V203 rat2        [V203,T37] (  3,  1.25)    long  ->   x2         "CSE for expectedClsNode"
@@ -623,8 +623,7 @@ G_M55449_IG30:        ; bbWeight=1, gcrefRegs=4180002 {x1 x19 x20 x26}, byrefReg
 G_M55449_IG31:        ; bbWeight=0.50, gcrefRegs=180000 {x19 x20}, byrefRegs=0000 {}, byref, isz
             asr     w1, w21, dotnet#31
             lsl     w1, w1, #1
-            add     w1, w1, w22,  ASR dotnet#31
-            negs    w1, w1
+            adds    w1, w1, w22,  ASR dotnet#31
             bne     G_M55449_IG32
             mov     x1, x19
             ; gcrRegs +[x1]
@@ -642,7 +641,7 @@ G_M55449_IG31:        ; bbWeight=0.50, gcrefRegs=180000 {x19 x20}, byrefRegs=000
             ; gcrRegs -[x1 x20]
             mov     w20, #1
             b       G_M55449_IG33
-						;; size=68 bbWeight=0.50 PerfScore 6.00
+						;; size=64 bbWeight=0.50 PerfScore 5.75
 G_M55449_IG32:        ; bbWeight=0.50, gcrefRegs=80000 {x19}, byrefRegs=0000 {}, byref
             mov     w20, wzr
 						;; size=4 bbWeight=0.50 PerfScore 0.25
@@ -776,7 +775,7 @@ G_M55449_IG46:        ; bbWeight=0, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
             brk     #0
 						;; size=40 bbWeight=0 PerfScore 0.00
 
-; Total bytes of code 1516, prolog size 48, PerfScore 174.78, instruction count 379, allocated bytes for code 1516 (MethodHash=a4562766) for method System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory_String():this (FullOpts)
+; Total bytes of code 1512, prolog size 48, PerfScore 174.53, instruction count 378, allocated bytes for code 1512 (MethodHash=a4562766) for method System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory_String():this (FullOpts)
 ; ============================================================
 
 Unwind Info:
@@ -787,7 +786,7 @@ Unwind Info:
   E bit             : 0
   X bit             : 0
   Vers              : 0
-  Function Length   : 379 (0x0017b) Actual length = 1516 (0x0005ec)
+  Function Length   : 378 (0x0017a) Actual length = 1512 (0x0005e8)
   ---- Epilog scopes ----
   ---- Scope 0
   Epilog Start Offset        : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
```

</div></details>

<details>
<summary>+0 (0.00%) : 223365.dasm -
System.Resources.Extensions.DeserializingResourceReader:CompareStringEqualsName(System.String):bool:this
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -106,7 +106,7 @@ G_M52056_IG05:        ; bbWeight=0.50, gcrefRegs=500000 {x20 x22}, byrefRegs=000
             ldr     x3, [x3]
             blr     x3
             ; gcrRegs -[x0-x1 x20 x22]
-            negs    w0, w0
+            cmp     w0, #0
             cset    x0, eq
 						;; size=40 bbWeight=0.50 PerfScore 4.25
 G_M52056_IG06:        ; bbWeight=0.50, epilog, nogc, extend
```

</div></details>

<details>
<summary><span style="color:green">-4</span> (<span
style="color:green">-0.02%</span>) : 106573.dasm -
System.Data.Tests.DataTableTest2:Select_ByFilter():this
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -3678,8 +3678,7 @@ G_M43941_IG97:        ; bbWeight=1, gcVars=0000000000000000000000000000000000000
 G_M43941_IG98:        ; bbWeight=4, gcrefRegs=4780004 {x2 x19 x20 x21 x22 x26}, byrefRegs=0000 {}, byref, isz
             ldr     w1, [x2, #0x08]
             ldr     w0, [fp, #0xD1FFAB1E]	// [V74 tmp49]
-            sub     w1, w0, w1
-            negs    w1, w1
+            subs    w1, w0, w1
             beq     G_M43941_IG90
             ldp     w0, w1, [x22, #0x10]
             add     w1, w1, #1
@@ -3688,7 +3687,7 @@ G_M43941_IG98:        ; bbWeight=4, gcrefRegs=4780004 {x2 x19 x20 x21 x22 x26},
             ldr     w1, [x2, #0x08]
             cmp     w1, w0
             bls     G_M43941_IG100
-						;; size=48 bbWeight=4 PerfScore 76.00
+						;; size=44 bbWeight=4 PerfScore 74.00
 G_M43941_IG99:        ; bbWeight=3.03, gcVars=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 {V06}, gcrefRegs=4780004 {x2 x19 x20 x21 x22 x26}, byrefRegs=0000 {}, gcvars, byref
             ; GC ptr vars -{V75}
             add     w1, w0, #1
@@ -7803,7 +7802,7 @@ RWD00  	dq	00740053002D0031h, 0067006E00690072h
 RWD16  	dq	007200740053002Dh, 00310067006E0069h
 
 
-; Total bytes of code 18184, prolog size 44, PerfScore 10435.99, instruction count 4546, allocated bytes for code 18184 (MethodHash=c958545a) for method System.Data.Tests.DataTableTest2:Select_ByFilter():this (FullOpts)
+; Total bytes of code 18180, prolog size 44, PerfScore 10433.99, instruction count 4545, allocated bytes for code 18180 (MethodHash=c958545a) for method System.Data.Tests.DataTableTest2:Select_ByFilter():this (FullOpts)
 ; ============================================================
 
 Unwind Info:
@@ -7814,7 +7813,7 @@ Unwind Info:
   E bit             : 0
   X bit             : 0
   Vers              : 0
-  Function Length   : 4130 (0x01022) Actual length = 16520 (0x004088)
+  Function Length   : 4129 (0x01021) Actual length = 16516 (0x004084)
   ---- Epilog scopes ----
   ---- Scope 0
   Epilog Start Offset        : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
```

</div></details>

<details>
<summary><span style="color:green">-4</span> (<span
style="color:green">-0.16%</span>) : 141855.dasm -
System.IO.Pipelines.Tests.PipePoolTests:GetMemoryOverMaxPoolSizeAllocatesArray():this
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -595,8 +595,7 @@ G_M36412_IG24:        ; bbWeight=1, gcrefRegs=B80000 {x19 x20 x21 x23}, byrefReg
 G_M36412_IG25:        ; bbWeight=0.50, gcrefRegs=B80000 {x19 x20 x21 x23}, byrefRegs=0000 {}, byref, isz
             asr     w1, w24, dotnet#31
             lsl     w1, w1, #1
-            add     w1, w1, w25,  ASR dotnet#31
-            negs    w1, w1
+            adds    w1, w1, w25,  ASR dotnet#31
             bne     G_M36412_IG26
             mov     x1, x20
             ; gcrRegs +[x1]
@@ -618,7 +617,7 @@ G_M36412_IG25:        ; bbWeight=0.50, gcrefRegs=B80000 {x19 x20 x21 x23}, byref
             ; gcrRegs -[x1] +[x0]
             ; gcr arg pop 0
             b       G_M36412_IG27
-						;; size=68 bbWeight=0.50 PerfScore 6.00
+						;; size=64 bbWeight=0.50 PerfScore 5.75
 G_M36412_IG26:        ; bbWeight=0.50, gcrefRegs=A80000 {x19 x21 x23}, byrefRegs=0000 {}, byref
             ; gcrRegs -[x0 x20]
             mov     x20, xzr
@@ -1232,7 +1231,7 @@ RWD16  	dq	<unknown method>
 	dq	G_M36412_IG51
 
 
-; Total bytes of code 2528, prolog size 48, PerfScore 347.37, instruction count 632, allocated bytes for code 2528 (MethodHash=f7d471c3) for method System.IO.Pipelines.Tests.PipePoolTests:GetMemoryOverMaxPoolSizeAllocatesArray():this (FullOpts)
+; Total bytes of code 2524, prolog size 48, PerfScore 347.12, instruction count 631, allocated bytes for code 2524 (MethodHash=f7d471c3) for method System.IO.Pipelines.Tests.PipePoolTests:GetMemoryOverMaxPoolSizeAllocatesArray():this (FullOpts)
 ; ============================================================
 
 Unwind Info:
@@ -1243,7 +1242,7 @@ Unwind Info:
   E bit             : 0
   X bit             : 0
   Vers              : 0
-  Function Length   : 591 (0x0024f) Actual length = 2364 (0x00093c)
+  Function Length   : 590 (0x0024e) Actual length = 2360 (0x000938)
   ---- Epilog scopes ----
   ---- Scope 0
   Epilog Start Offset        : 3523193630 (0xd1ffab1e) Actual offset = 3523193630 (0xd1ffab1e) Offset from main function begin = 3523193630 (0xd1ffab1e)
```

</div></details>


</div></details>

<details>
<summary>benchmarks.run.linux.arm64.checked.mch</summary>
<div style="margin-left:1em">


<details>
<summary>+0 (0.00%) : 3177.dasm -
System.Resources.ResourceReader:CompareStringEqualsName(System.String):bool:this
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -106,7 +106,7 @@ G_M1070_IG05:        ; bbWeight=0.50, gcrefRegs=500000 {x20 x22}, byrefRegs=0000
             ldr     x3, [x3]
             blr     x3
             ; gcrRegs -[x0-x1 x20 x22]
-            negs    w0, w0
+            cmp     w0, #0
             cset    x0, eq
 						;; size=40 bbWeight=0.50 PerfScore 4.25
 G_M1070_IG06:        ; bbWeight=0.50, epilog, nogc, extend
```

</div></details>


</div></details>

<details>
<summary>smoke_tests.nativeaot.linux.arm64.checked.mch</summary>
<div style="margin-left:1em">


<details>
<summary>+0 (0.00%) : 18583.dasm -
Generics+TestAsyncGVMScenarios:RunAsync() (FullOpts)</summary>
<div style="margin-left:1em">

No diffs found?

</div></details>

<details>
<summary>+0 (0.00%) : 18730.dasm -
Generics+TestAsyncGVMScenarios:AsyncGvm1[System.__Canon]():this
(FullOpts)</summary>
<div style="margin-left:1em">

No diffs found?

</div></details>

<details>
<summary>+0 (0.00%) : 18865.dasm -
Generics+TestAsyncGVMScenarios:AsyncGvm2[System.__Canon]():this
(FullOpts)</summary>
<div style="margin-left:1em">

No diffs found?

</div></details>

<details>
<summary>+0 (0.00%) : 18873.dasm -
System.Threading.Tasks.Task:get_CompletedTask() (FullOpts)</summary>
<div style="margin-left:1em">

No diffs found?

</div></details>


</div></details>


</div></details>

<details>
<summary>Details</summary>
<div style="margin-left:1em">

#### Size improvements/regressions per collection

|Collection|Contexts with diffs|Improvements|Regressions|Same
size|Improvements (bytes)|Regressions (bytes)|
|---|--:|--:|--:|--:|--:|--:|

|libraries_tests_no_tiered_compilation.run.linux.arm64.Release.mch|11|<span
style="color:green">10</span>|<span style="color:red">0</span>|<span
style="color:blue">1</span>|<span style="color:green">-40</span>|<span
style="color:red">+0</span>|
|benchmarks.run.linux.arm64.checked.mch|1|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">1</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
|smoke_tests.nativeaot.linux.arm64.checked.mch|4|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">4</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
||16|<span style="color:green">10</span>|<span
style="color:red">0</span>|<span style="color:blue">6</span>|<span
style="color:green">-40</span>|<span style="color:red">+0</span>|

---

#### PerfScore improvements/regressions per collection

|Collection|Contexts with diffs|Improvements|Regressions|Same
PerfScore|Improvements (PerfScore)|Regressions (PerfScore)|PerfScore
Overall in FullOpts|
|---|--:|--:|--:|--:|--:|--:|--:|

|libraries_tests_no_tiered_compilation.run.linux.arm64.Release.mch|11|<span
style="color:green">10</span>|<span style="color:red">0</span>|<span
style="color:blue">1</span>|<span
style="color:green">-0.10%</span>|0.00%|<span
style="color:green">-0.0000%</span>|
|benchmarks.run.linux.arm64.checked.mch|1|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">1</span>|0.00%|0.00%|0.0000%|
|smoke_tests.nativeaot.linux.arm64.checked.mch|4|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">4</span>|0.00%|0.00%|0.0000%|

---

#### Context information

|Collection|Diffed contexts|MinOpts|FullOpts|Missed, base|Missed, diff|
|---|--:|--:|--:|--:|--:|

|libraries_tests_no_tiered_compilation.run.linux.arm64.Release.mch|354,001|23,273|330,728|0
(0.00%)|0 (0.00%)|
|benchmarks.run.linux.arm64.checked.mch|63,204|3,337|59,867|0 (0.00%)|0
(0.00%)|
|smoke_tests.nativeaot.linux.arm64.checked.mch|18,890|8|18,882|0
(0.00%)|0 (0.00%)|
||436,095|26,618|409,477|0 (0.00%)|0 (0.00%)|


---

#### jit-analyze output

<details>

<summary>libraries_tests_no_tiered_compilation.run.linux.arm64.Release.mch</summary>
<div style="margin-left:1em">

```

Summary of Code Size diffs:
(Lower is better)

Total bytes of base: 183146276 (overridden on cmd)
Total bytes of diff: 183146236 (overridden on cmd)
Total bytes of delta: -40 (-0.00 % of base)
    diff is an improvement.
    relative diff is an improvement.
```
<details>

<summary>Detail diffs</summary>

```


Top file improvements (bytes):
          -4 : 162916.dasm (-0.242% of base)
          -4 : 141852.dasm (-0.162% of base)
          -4 : 141855.dasm (-0.158% of base)
          -4 : 141861.dasm (-0.201% of base)
          -4 : 162917.dasm (-0.269% of base)
          -4 : 142473.dasm (-1.266% of base)
          -4 : 142389.dasm (-0.182% of base)
          -4 : 162915.dasm (-0.264% of base)
          -4 : 162918.dasm (-0.185% of base)
          -4 : 106573.dasm (-0.022% of base)

10 total files with Code Size differences (10 improved, 0 regressed), 1 unchanged.

Top method improvements (bytes):
          -4 (-0.022% of base) : 106573.dasm - System.Data.Tests.DataTableTest2:Select_ByFilter():this (FullOpts)
          -4 (-1.266% of base) : 142473.dasm - System.IO.Pipelines.Tests.BufferSegmentPoolTest:GetSegments(System.IO.Pipelines.ReadResult):System.Collections.Generic.List`1[System.Buffers.ReadOnlySequenceSegment`1[byte]] (FullOpts)
          -4 (-0.182% of base) : 142389.dasm - System.IO.Pipelines.Tests.PipelineReaderWriterFacts:ResetAfterCompleteReaderAndWriterWithoutAdvancingClearsEverything():this (FullOpts)
          -4 (-0.162% of base) : 141852.dasm - System.IO.Pipelines.Tests.PipePoolTests:GetMemoryAtMaxPoolSizeAllocatesFromPool():this (FullOpts)
          -4 (-0.158% of base) : 141855.dasm - System.IO.Pipelines.Tests.PipePoolTests:GetMemoryOverMaxPoolSizeAllocatesArray():this (FullOpts)
          -4 (-0.201% of base) : 141861.dasm - System.IO.Pipelines.Tests.PipePoolTests:WritesToArrayPoolByDefault():this (FullOpts)
          -4 (-0.242% of base) : 162916.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_IMemoryList_MultiBlock():this (FullOpts)
          -4 (-0.185% of base) : 162918.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_IMemoryList_SingleBlock():this (FullOpts)
          -4 (-0.264% of base) : 162915.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory_String():this (FullOpts)
          -4 (-0.269% of base) : 162917.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory():this (FullOpts)

Top method improvements (percentages):
          -4 (-1.266% of base) : 142473.dasm - System.IO.Pipelines.Tests.BufferSegmentPoolTest:GetSegments(System.IO.Pipelines.ReadResult):System.Collections.Generic.List`1[System.Buffers.ReadOnlySequenceSegment`1[byte]] (FullOpts)
          -4 (-0.269% of base) : 162917.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory():this (FullOpts)
          -4 (-0.264% of base) : 162915.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_Memory_String():this (FullOpts)
          -4 (-0.242% of base) : 162916.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_IMemoryList_MultiBlock():this (FullOpts)
          -4 (-0.201% of base) : 141861.dasm - System.IO.Pipelines.Tests.PipePoolTests:WritesToArrayPoolByDefault():this (FullOpts)
          -4 (-0.185% of base) : 162918.dasm - System.Memory.Tests.ReadOnlySequenceTryGetTests:Ctor_IMemoryList_SingleBlock():this (FullOpts)
          -4 (-0.182% of base) : 142389.dasm - System.IO.Pipelines.Tests.PipelineReaderWriterFacts:ResetAfterCompleteReaderAndWriterWithoutAdvancingClearsEverything():this (FullOpts)
          -4 (-0.162% of base) : 141852.dasm - System.IO.Pipelines.Tests.PipePoolTests:GetMemoryAtMaxPoolSizeAllocatesFromPool():this (FullOpts)
          -4 (-0.158% of base) : 141855.dasm - System.IO.Pipelines.Tests.PipePoolTests:GetMemoryOverMaxPoolSizeAllocatesArray():this (FullOpts)
          -4 (-0.022% of base) : 106573.dasm - System.Data.Tests.DataTableTest2:Select_ByFilter():this (FullOpts)

10 total methods with Code Size differences (10 improved, 0 regressed).

```

</details>


--------------------------------------------------------------------------------



</div></details>

<details>
<summary>benchmarks.run.linux.arm64.checked.mch</summary>
<div style="margin-left:1em">

```

Summary of Code Size diffs:
(Lower is better)

Total bytes of base: 21285888 (overridden on cmd)
Total bytes of diff: 21285888 (overridden on cmd)
Total bytes of delta: 0 (0.00 % of base)
```
<details>

<summary>Detail diffs</summary>

```


0 total files with Code Size differences (0 improved, 0 regressed), 1 unchanged.

0 total methods with Code Size differences (0 improved, 0 regressed).

```

</details>


--------------------------------------------------------------------------------



</div></details>


</div></details>

x64 asmdiffs
Diffs are based on <span style="color:#1460aa">2,787,549</span> contexts
(<span style="color:#1460aa">1,078,277</span> MinOpts, <span
style="color:#1460aa">1,709,272</span> FullOpts).


<details>
<summary>Overall (<span style="color:green">-116</span> bytes)</summary>
<div style="margin-left:1em">

|Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs
|---|--:|--:|--:|
|coreclr_tests.run.linux.x64.checked.mch|305,501,642|<span
style="color:green">-110</span>|<span
style="color:green">-14.87%</span>|

|libraries_tests_no_tiered_compilation.run.linux.x64.Release.mch|157,729,192|<span
style="color:green">-2</span>|<span style="color:green">-0.01%</span>|
|libraries_tests.run.linux.x64.Release.mch|392,784,680|<span
style="color:green">-4</span>|<span style="color:green">-0.01%</span>|


</div></details>

<details>
<summary>MinOpts (<span style="color:green">-14</span> bytes)</summary>
<div style="margin-left:1em">

|Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs
|---|--:|--:|--:|
|coreclr_tests.run.linux.x64.checked.mch|197,469,852|<span
style="color:green">-10</span>|<span style="color:green">-1.28%</span>|
|libraries_tests.run.linux.x64.Release.mch|215,792,030|<span
style="color:green">-4</span>|<span style="color:green">-0.01%</span>|


</div></details>

<details>
<summary>FullOpts (<span style="color:green">-102</span>
bytes)</summary>
<div style="margin-left:1em">

|Collection|Base size (bytes)|Diff size (bytes)|PerfScore in Diffs
|---|--:|--:|--:|
|coreclr_tests.run.linux.x64.checked.mch|108,031,790|<span
style="color:green">-100</span>|<span
style="color:green">-16.74%</span>|

|libraries_tests_no_tiered_compilation.run.linux.x64.Release.mch|146,383,976|<span
style="color:green">-2</span>|<span style="color:green">-0.01%</span>|


</div></details>

<details>
<summary>Example diffs</summary>
<div style="margin-left:1em">


<details>
<summary>coreclr_tests.run.linux.x64.checked.mch</summary>
<div style="margin-left:1em">


<details>
<summary><span style="color:green">-8</span> (<span
style="color:green">-29.63%</span>) : 199901.dasm -
TestNeg.Program:NegsBinOpSingleLine(int,int):bool (FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -18,23 +18,19 @@ G_M18888_IG01:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
 						;; size=0 bbWeight=1 PerfScore 0.00
 G_M18888_IG02:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
        sar      edi, 1
-       mov      eax, edi
-       neg      eax
        setne    al
        movzx    rax, al
-       add      esi, esi
-       mov      ecx, esi
-       neg      ecx
+       shl      esi, 1
        setne    cl
        movzx    rcx, cl
        or       eax, ecx
-						;; size=26 bbWeight=1 PerfScore 4.50
+						;; size=18 bbWeight=1 PerfScore 3.75
 G_M18888_IG03:        ; bbWeight=1, epilog, nogc, extend
        ret      
 						;; size=1 bbWeight=1 PerfScore 1.00
 ; END METHOD TestNeg.Program:NegsBinOpSingleLine(int,int):bool
 
-; Total bytes of code 27, prolog size 0, PerfScore 5.50, instruction count 12, allocated bytes for code 27 (MethodHash=d08ab637) for method TestNeg.Program:NegsBinOpSingleLine(int,int):bool (FullOpts)
+; Total bytes of code 19, prolog size 0, PerfScore 4.75, instruction count 8, allocated bytes for code 19 (MethodHash=d08ab637) for method TestNeg.Program:NegsBinOpSingleLine(int,int):bool (FullOpts)
 ; ============================================================
 
 Unwind Info:
```

</div></details>

<details>
<summary><span style="color:green">-7</span> (<span
style="color:green">-29.17%</span>) : 199894.dasm -
TestNeg.Program:NegsLSR(uint):int (FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -16,20 +16,17 @@
 G_M6300_IG01:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, nogc <-- Prolog IG
 						;; size=0 bbWeight=0.50 PerfScore 0.00
 G_M6300_IG02:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
+       mov      eax, -1
+       mov      ecx, 1
        shr      edi, 3
-       mov      eax, edi
-       mov      ecx, -1
-       mov      edx, 1
-       neg      rax
-       mov      eax, edx
-       cmove    eax, ecx
-						;; size=23 bbWeight=0.50 PerfScore 1.00
+       cmovne   eax, ecx
+						;; size=16 bbWeight=0.50 PerfScore 0.62
 G_M6300_IG03:        ; bbWeight=0.50, epilog, nogc, extend
        ret      
 						;; size=1 bbWeight=0.50 PerfScore 0.50
 ; END METHOD TestNeg.Program:NegsLSR(uint):int
 
-; Total bytes of code 24, prolog size 0, PerfScore 1.50, instruction count 8, allocated bytes for code 24 (MethodHash=2a8ee763) for method TestNeg.Program:NegsLSR(uint):int (FullOpts)
+; Total bytes of code 17, prolog size 0, PerfScore 1.12, instruction count 5, allocated bytes for code 17 (MethodHash=2a8ee763) for method TestNeg.Program:NegsLSR(uint):int (FullOpts)
 ; ============================================================
 
 Unwind Info:
```

</div></details>

<details>
<summary><span style="color:green">-7</span> (<span
style="color:green">-29.17%</span>) : 199896.dasm -
TestNeg.Program:NegsLargeShift(uint):int (FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -16,20 +16,17 @@
 G_M11276_IG01:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, nogc <-- Prolog IG
 						;; size=0 bbWeight=0.50 PerfScore 0.00
 G_M11276_IG02:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
+       mov      eax, -1
+       mov      ecx, 1
        shl      edi, 4
-       mov      eax, edi
-       mov      ecx, -1
-       mov      edx, 1
-       neg      rax
-       mov      eax, edx
-       cmove    eax, ecx
-						;; size=23 bbWeight=0.50 PerfScore 1.00
+       cmovne   eax, ecx
+						;; size=16 bbWeight=0.50 PerfScore 0.62
 G_M11276_IG03:        ; bbWeight=0.50, epilog, nogc, extend
        ret      
 						;; size=1 bbWeight=0.50 PerfScore 0.50
 ; END METHOD TestNeg.Program:NegsLargeShift(uint):int
 
-; Total bytes of code 24, prolog size 0, PerfScore 1.50, instruction count 8, allocated bytes for code 24 (MethodHash=43eed3f3) for method TestNeg.Program:NegsLargeShift(uint):int (FullOpts)
+; Total bytes of code 17, prolog size 0, PerfScore 1.12, instruction count 5, allocated bytes for code 17 (MethodHash=43eed3f3) for method TestNeg.Program:NegsLargeShift(uint):int (FullOpts)
 ; ============================================================
 
 Unwind Info:
```

</div></details>

<details>
<summary><span style="color:green">-5</span> (<span
style="color:green">-1.71%</span>) : 531325.dasm -
ILGEN_CLASS:ILGEN_METHOD(bool,char,short,int):char (Tier0)</summary>
<div style="margin-left:1em">

```diff
@@ -74,16 +74,14 @@ G_M28265_IG02:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref,
        mov      qword ptr [rbp-0x40], rdx
        mov      rax, qword ptr [rbp-0x40]
        mov      qword ptr [rbp-0x48], rax
-       mov      eax, dword ptr [rbp-0x28]
-       neg      rax
-       test     rax, rax
+       cmp      dword ptr [rbp-0x28], 0
        jne      SHORT G_M28265_IG03
        mov      eax, dword ptr [rbp-0x18]
        cmp      eax, 255
        ja       SHORT G_M28265_IG06
        mov      eax, eax
        mov      byte  ptr [rbp-0x04], al
-						;; size=182 bbWeight=1 PerfScore 117.08
+						;; size=177 bbWeight=1 PerfScore 117.58
 G_M28265_IG03:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz
        mov      eax, dword ptr [rbp-0x10]
        cmp      rax, qword ptr [rbp-0x48]
@@ -116,7 +114,7 @@ RWD16  	dq	8000000000000000h	;           -0
 RWD24  	dd	4F0BD98Fh		; 2.34629e+09
 
 
-; Total bytes of code 293, prolog size 31, PerfScore 147.42, instruction count 75, allocated bytes for code 293 (MethodHash=d26f9196) for method ILGEN_CLASS:ILGEN_METHOD(bool,char,short,int):char (Tier0)
+; Total bytes of code 288, prolog size 31, PerfScore 147.92, instruction count 73, allocated bytes for code 288 (MethodHash=d26f9196) for method ILGEN_CLASS:ILGEN_METHOD(bool,char,short,int):char (Tier0)
 ; ============================================================
 
 Unwind Info:
```

</div></details>

<details>
<summary><span style="color:green">-2</span> (<span
style="color:green">-4.17%</span>) : 181410.dasm -
ldc_neg_i4._neg:i4_3(int,int):int (MinOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -30,18 +30,17 @@ G_M1458_IG03:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byre
 						;; size=5 bbWeight=0.50 PerfScore 0.50
 G_M1458_IG04:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
        xor      eax, eax
-       neg      eax
        test     eax, eax
        sete     al
        movzx    rax, al
-						;; size=12 bbWeight=1 PerfScore 2.00
+						;; size=10 bbWeight=1 PerfScore 1.75
 G_M1458_IG05:        ; bbWeight=1, epilog, nogc, extend
        add      rsp, 16
        pop      rbp
        ret      
 						;; size=6 bbWeight=1 PerfScore 1.75
 
-; Total bytes of code 48, prolog size 16, PerfScore 12.00, instruction count 16, allocated bytes for code 48 (MethodHash=0125fa4d) for method ldc_neg_i4._neg:i4_3(int,int):int (MinOpts)
+; Total bytes of code 46, prolog size 16, PerfScore 11.75, instruction count 15, allocated bytes for code 46 (MethodHash=0125fa4d) for method ldc_neg_i4._neg:i4_3(int,int):int (MinOpts)
 ; ============================================================
 
 Unwind Info:
```

</div></details>

<details>
<summary><span style="color:green">-3</span> (<span
style="color:green">-5.77%</span>) : 181421.dasm -
ldc_neg_i8._neg:i8_3(long,long):int (MinOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -30,18 +30,17 @@ G_M18290_IG03:        ; bbWeight=0.50, gcrefRegs=0000 {}, byrefRegs=0000 {}, byr
 						;; size=5 bbWeight=0.50 PerfScore 0.50
 G_M18290_IG04:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
        xor      eax, eax
-       neg      rax
        test     rax, rax
        sete     al
        movzx    rax, al
-						;; size=14 bbWeight=1 PerfScore 2.00
+						;; size=11 bbWeight=1 PerfScore 1.75
 G_M18290_IG05:        ; bbWeight=1, epilog, nogc, extend
        add      rsp, 16
        pop      rbp
        ret      
 						;; size=6 bbWeight=1 PerfScore 1.75
 
-; Total bytes of code 52, prolog size 18, PerfScore 12.00, instruction count 16, allocated bytes for code 52 (MethodHash=ff46b88d) for method ldc_neg_i8._neg:i8_3(long,long):int (MinOpts)
+; Total bytes of code 49, prolog size 18, PerfScore 11.75, instruction count 15, allocated bytes for code 49 (MethodHash=ff46b88d) for method ldc_neg_i8._neg:i8_3(long,long):int (MinOpts)
 ; ============================================================
 
 Unwind Info:
```

</div></details>


</div></details>

<details>

<summary>libraries_tests_no_tiered_compilation.run.linux.x64.Release.mch</summary>
<div style="margin-left:1em">


<details>
<summary><span style="color:green">-2</span> (<span
style="color:green">-0.01%</span>) : 124444.dasm -
System.Data.Tests.DataTableTest2:Select_ByFilter():this
(FullOpts)</summary>
<div style="margin-left:1em">

```diff
@@ -3246,7 +3246,6 @@ G_M43941_IG102:        ; bbWeight=1, gcVars=000000000000000000000000000000000000
 G_M43941_IG103:        ; bbWeight=4, gcrefRegs=F009 {rax rbx r12 r13 r14 r15}, byrefRegs=0000 {}, byref, isz
        mov      esi, dword ptr [rbp-0x30]
        sub      esi, dword ptr [rax+0x08]
-       neg      esi
        je       G_M43941_IG96
        inc      dword ptr [r13+0x14]
        mov      rdi, gword ptr [r13+0x08]
@@ -3254,7 +3253,7 @@ G_M43941_IG103:        ; bbWeight=4, gcrefRegs=F009 {rax rbx r12 r13 r14 r15}, b
        mov      esi, dword ptr [r13+0x10]
        cmp      dword ptr [rdi+0x08], esi
        jbe      SHORT G_M43941_IG106
-						;; size=31 bbWeight=4 PerfScore 65.00
+						;; size=29 bbWeight=4 PerfScore 64.00
 G_M43941_IG104:        ; bbWeight=3.05, gcVars=00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002 {V06}, gcrefRegs=F088 {rbx rdi r12 r13 r14 r15}, byrefRegs=0000 {}, gcvars, byref
        ; gcrRegs -[rax]
        ; GC ptr vars -{V75}
@@ -6658,7 +6657,7 @@ RWD40  	dq	4034000000000000h	;           20
 RWD48  	dq	4039000000000000h	;           25
 
 
-; Total bytes of code 14316, prolog size 28, PerfScore 7866.28, instruction count 3034, allocated bytes for code 14316 (MethodHash=c958545a) for method System.Data.Tests.DataTableTest2:Select_ByFilter():this (FullOpts)
+; Total bytes of code 14314, prolog size 28, PerfScore 7865.28, instruction count 3033, allocated bytes for code 14314 (MethodHash=c958545a) for method System.Data.Tests.DataTableTest2:Select_ByFilter():this (FullOpts)
 ; ============================================================
 
 Unwind Info:
```

</div></details>


</div></details>

<details>
<summary>libraries_tests.run.linux.x64.Release.mch</summary>
<div style="margin-left:1em">


<details>
<summary><span style="color:green">-4</span> (<span
style="color:green">-0.03%</span>) : 314396.dasm -
System.Data.Tests.DataTableTest2:Select_ByFilter():this (Instrumented
Tier0)</summary>
<div style="margin-left:1em">

```diff
@@ -2199,13 +2199,11 @@ G_M43941_IG57:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
        ; gcr arg pop 0
        mov      ecx, dword ptr [rbp-0x240]
        sub      ecx, dword ptr [rax]
-       mov      eax, ecx
-       ; byrRegs -[rax]
-       neg      eax
-       test     eax, eax
+       test     ecx, ecx
        je       G_M43941_IG56
        mov      rdi, 0xD1FFAB1E
        call     CORINFO_HELP_COUNTPROFILE32
+       ; byrRegs -[rax]
        ; gcr arg pop 0
        mov      rdi, gword ptr [rbp-0x50]
        ; gcrRegs +[rdi]
@@ -2215,7 +2213,7 @@ G_M43941_IG57:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref
        call     [<unknown method>]
        ; gcrRegs -[rsi rdi]
        ; gcr arg pop 0
-						;; size=309 bbWeight=1 PerfScore 58.00
+						;; size=305 bbWeight=1 PerfScore 57.50
 G_M43941_IG58:        ; bbWeight=1, gcrefRegs=0000 {}, byrefRegs=0000 {}, byref, isz
        mov      eax, dword ptr [rbp-0x5E0]
        dec      eax
@@ -5412,7 +5410,7 @@ RWD08  	dq	4034000000000000h	;           20
 RWD16  	dq	4039000000000000h	;           25
 
 
-; Total bytes of code 15982, prolog size 67, PerfScore 3425.70, instruction count 2755, allocated bytes for code 15982 (MethodHash=c958545a) for method System.Data.Tests.DataTableTest2:Select_ByFilter():this (Instrumented Tier0)
+; Total bytes of code 15978, prolog size 67, PerfScore 3425.20, instruction count 2753, allocated bytes for code 15978 (MethodHash=c958545a) for method System.Data.Tests.DataTableTest2:Select_ByFilter():this (Instrumented Tier0)
 ; ============================================================
 
 Unwind Info:
```

</div></details>


</div></details>


</div></details>

<details>
<summary>Details</summary>
<div style="margin-left:1em">

#### Size improvements/regressions per collection

|Collection|Contexts with diffs|Improvements|Regressions|Same
size|Improvements (bytes)|Regressions (bytes)|
|---|--:|--:|--:|--:|--:|--:|
|benchmarks.run.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
|benchmarks.run_pgo.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
|benchmarks.run_pgo_optrepeat.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
|coreclr_tests.run.linux.x64.checked.mch|23|<span
style="color:green">23</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-110</span>|<span
style="color:red">+0</span>|
|libraries.crossgen2.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
|libraries.pmi.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|

|libraries_tests_no_tiered_compilation.run.linux.x64.Release.mch|1|<span
style="color:green">1</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-2</span>|<span
style="color:red">+0</span>|
|libraries_tests.run.linux.x64.Release.mch|1|<span
style="color:green">1</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-4</span>|<span
style="color:red">+0</span>|
|realworld.run.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
|smoke_tests.nativeaot.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span style="color:green">-0</span>|<span
style="color:red">+0</span>|
||25|<span style="color:green">25</span>|<span
style="color:red">0</span>|<span style="color:blue">0</span>|<span
style="color:green">-116</span>|<span style="color:red">+0</span>|

---

#### PerfScore improvements/regressions per collection

|Collection|Contexts with diffs|Improvements|Regressions|Same
PerfScore|Improvements (PerfScore)|Regressions (PerfScore)|PerfScore
Overall in FullOpts|
|---|--:|--:|--:|--:|--:|--:|--:|
|benchmarks.run.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|0.00%|0.00%|0.0000%|
|benchmarks.run_pgo.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|0.00%|0.00%|0.0000%|
|benchmarks.run_pgo_optrepeat.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|0.00%|0.00%|0.0000%|
|coreclr_tests.run.linux.x64.checked.mch|23|<span
style="color:green">22</span>|<span style="color:red">1</span>|<span
style="color:blue">0</span>|<span
style="color:green">-15.50%</span>|<span
style="color:red">+0.34%</span>|<span
style="color:green">-0.0017%</span>|
|libraries.crossgen2.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|0.00%|0.00%|0.0000%|
|libraries.pmi.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|0.00%|0.00%|0.0000%|

|libraries_tests_no_tiered_compilation.run.linux.x64.Release.mch|1|<span
style="color:green">1</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span
style="color:green">-0.01%</span>|0.00%|<span
style="color:green">-0.0000%</span>|
|libraries_tests.run.linux.x64.Release.mch|1|<span
style="color:green">1</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|<span
style="color:green">-0.01%</span>|0.00%|0.0000%|
|realworld.run.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|0.00%|0.00%|0.0000%|
|smoke_tests.nativeaot.linux.x64.checked.mch|0|<span
style="color:green">0</span>|<span style="color:red">0</span>|<span
style="color:blue">0</span>|0.00%|0.00%|0.0000%|

---

#### Context information

|Collection|Diffed contexts|MinOpts|FullOpts|Missed, base|Missed, diff|
|---|--:|--:|--:|--:|--:|
|benchmarks.run.linux.x64.checked.mch|75,913|2,972|72,941|0 (0.00%)|0
(0.00%)|
|benchmarks.run_pgo.linux.x64.checked.mch|122,785|86,206|36,579|0
(0.00%)|0 (0.00%)|

|benchmarks.run_pgo_optrepeat.linux.x64.checked.mch|76,998|2,939|74,059|0
(0.00%)|0 (0.00%)|
|coreclr_tests.run.linux.x64.checked.mch|577,098|358,595|218,503|0
(0.00%)|0 (0.00%)|
|libraries.crossgen2.linux.x64.checked.mch|269,385|20|269,365|0
(0.00%)|0 (0.00%)|
|libraries.pmi.linux.x64.checked.mch|354,706|8|354,698|0 (0.00%)|0
(0.00%)|

|libraries_tests_no_tiered_compilation.run.linux.x64.Release.mch|387,764|23,607|364,157|0
(0.00%)|0 (0.00%)|
|libraries_tests.run.linux.x64.Release.mch|862,114|603,896|258,218|0
(0.00%)|0 (0.00%)|
|realworld.run.linux.x64.checked.mch|29,264|21|29,243|0 (0.00%)|0
(0.00%)|
|smoke_tests.nativeaot.linux.x64.checked.mch|31,522|13|31,509|0
(0.00%)|0 (0.00%)|
||2,787,549|1,078,277|1,709,272|0 (0.00%)|0 (0.00%)|


---

#### jit-analyze output


</div></details>
tannergooding pushed a commit that referenced this pull request Apr 15, 2026
Scan method body instructions for all opcodes which take a token operand.
Create static dependency nodes for all tokens found.
Rewrite the method body when writing output to update all tokens in it.

I improved the tests to validate member removal as well.

Implementation notes:
- Brings in ILReader and ILOpcode form the type system
- For now implemented ThrowHelper stub since the type system code uses this.

What's missing:
Scanning exception regions and reporting dependencies for tokens in them
Rewriting exception regions and updating tokens in them
I added MichalStrehovsky/iltrim#17 to track that work.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants