Skip to content

JIT generates better code when expression is stored in variable #102273

@oleg-st

Description

@oleg-st

Description

Code:

using System.Runtime.CompilerServices;
using System.Numerics;

public unsafe class C {
    
    public unsafe struct BIT_DStream_t
    {
        public nuint bitContainer;
        public uint bitsConsumed;
        public sbyte* ptr;
        public sbyte* start;
        public sbyte* limitPtr;
    }
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static nuint BIT_initDStream1(ref BIT_DStream_t bitD, void* srcBuffer, nuint srcSize)
    {
        byte lastByte = ((byte*)srcBuffer)[srcSize - 1];
        bitD.bitsConsumed = lastByte != 0 ? 8 - (uint)BitOperations.Log2(lastByte) : 0;
        
        return 0;
    }
    
    [MethodImpl(MethodImplOptions.AggressiveInlining)]
    private static nuint BIT_initDStream2(ref BIT_DStream_t bitD, void* srcBuffer, nuint srcSize)
    {
        byte lastByte = ((byte*)srcBuffer)[srcSize - 1];
        // difference here
        var v = lastByte != 0 ? 8 - (uint)BitOperations.Log2(lastByte) : 0;
        bitD.bitsConsumed = v;
        
        return 0;
    }
    
    private static nuint M1(byte *ip, byte *iend) {
        BIT_DStream_t seqState_DStream = new ();
        BIT_initDStream1(ref seqState_DStream, ip, (nuint)(iend - ip));
        return seqState_DStream.bitContainer;
    }
    
    private static nuint M2(byte *ip, byte *iend) {
        BIT_DStream_t seqState_DStream = new ();
        BIT_initDStream2(ref seqState_DStream, ip, (nuint)(iend - ip));
        return seqState_DStream.bitContainer;
    }
}

M1:

    L0000: sub rsp, 0x28
    L0004: vxorps xmm4, xmm4, xmm4
    L0008: vmovdqa [rsp], xmm4
    L000d: vmovdqa [rsp+0x10], xmm4
    L0013: xor eax, eax
    L0015: mov [rsp+0x20], rax
    L001a: sub rdx, rcx
    L001d: movzx eax, byte ptr [rdx+rcx-1]
    L0022: lea rcx, [rsp]
    L0026: test eax, eax
    L0028: jne short L002e
    L002a: xor edx, edx
    L002c: jmp short L003f
    L002e: or eax, 1
    L0031: xor edx, edx
    L0033: lzcnt edx, eax
    L0037: xor edx, 0x1f
    L003a: neg edx
    L003c: add edx, 8
    L003f: mov [rcx+8], edx
    L0042: mov rax, [rsp]
    L0046: add rsp, 0x28
    L004a: ret

M2:

    L0000: sub rdx, rcx
    L0003: movsx rax, byte ptr [rdx+rcx-1]
    L0009: xor eax, eax
    L000b: ret

SharpLab

Configuration

.NET 8.0.204

Metadata

Metadata

Assignees

Labels

Priority:2Work that is important, but not critical for the releasearea-CodeGen-coreclrCLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMItenet-performancePerformance related issue

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions