Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unnecessary LdelemaRef call not elided with Volatile.Read #65789

Closed
Tracked by #93172
stephentoub opened this issue Feb 23, 2022 · 4 comments · Fixed by #85256
Closed
Tracked by #93172

Unnecessary LdelemaRef call not elided with Volatile.Read #65789

stephentoub opened this issue Feb 23, 2022 · 4 comments · Fixed by #85256
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI in-pr There is an active PR which will close this issue when it is merged
Milestone

Comments

@stephentoub
Copy link
Member

stephentoub commented Feb 23, 2022

Consider the code:

using System;
using System.Threading;

public sealed class C
{
    private readonly C[] _array;
    
    public C Get1() => Volatile.Read(ref _array[0]);
    
    public C Get2() => _array[0];
}

We shouldn't need a helper to read a value from the array, but even though the Volatile.Read evaporates on x86/64, we're still left with a non-inlined CastHelpers.LdelemaRef call in Get1:

; Core CLR 6.0.121.56705 on x86

C.Get1()
    L0000: mov ecx, [ecx+4]
    L0003: push 0x1171c6d8
    L0008: xor edx, edx
    L000a: call System.Runtime.CompilerServices.CastHelpers.LdelemaRef(System.Array, Int32, Void*)
    L000f: mov eax, [eax]
    L0011: ret

C.Get2()
    L0000: mov eax, [ecx+4]
    L0003: cmp dword ptr [eax+4], 0
    L0007: jbe short L000d
    L0009: mov eax, [eax+8]
    L000c: ret
    L000d: call 0x722c5fc0
    L0012: int3

; Core CLR 6.0.121.56705 on amd64

C.Get1()
    L0000: sub rsp, 0x28
    L0004: mov rcx, [rcx+8]
    L0008: xor edx, edx
    L000a: mov r8, 0x7ffaab0fccd0
    L0014: call 0x00007ffa9fda8200
    L0019: mov rax, [rax]
    L001c: add rsp, 0x28
    L0020: ret

C.Get2()
    L0000: sub rsp, 0x28
    L0004: mov rax, [rcx+8]
    L0008: cmp dword ptr [rax+8], 0
    L000c: jbe short L0017
    L000e: mov rax, [rax+0x10]
    L0012: add rsp, 0x28
    L0016: ret
    L0017: call 0x00007ffaffa6ec10
    L001c: int3

SharpLab

category:cq
theme:volatile

@dotnet-issue-labeler dotnet-issue-labeler bot added area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI untriaged New issue has not been triaged by the area owner labels Feb 23, 2022
@ghost
Copy link

ghost commented Feb 23, 2022

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

Issue Details

Consider the code:

using System;
using System.Threading;

public sealed class C
{
    private readonly C[] _array;
    
    public C Get1() => Volatile.Read(ref _array[0]);
    
    public C Get2() => _array[0];
}

We shouldn't need a helper to read a value from the array, but even though the Volatile.Read evaporates on x86/64, we're still left with a non-inlined CastHelpers.LdelemaRef call in Get1:

; Core CLR 6.0.121.56705 on x86

C.Get1()
    L0000: mov ecx, [ecx+4]
    L0003: push 0x1171c6d8
    L0008: xor edx, edx
    L000a: call System.Runtime.CompilerServices.CastHelpers.LdelemaRef(System.Array, Int32, Void*)
    L000f: mov eax, [eax]
    L0011: ret

C.Get2()
    L0000: mov eax, [ecx+4]
    L0003: cmp dword ptr [eax+4], 0
    L0007: jbe short L000d
    L0009: mov eax, [eax+8]
    L000c: ret
    L000d: call 0x722c5fc0
    L0012: int3

; Core CLR 6.0.121.56705 on amd64

C.Get1()
    L0000: sub rsp, 0x28
    L0004: mov rcx, [rcx+8]
    L0008: xor edx, edx
    L000a: mov r8, 0x7ffaab0fccd0
    L0014: call 0x00007ffa9fda8200
    L0019: mov rax, [rax]
    L001c: add rsp, 0x28
    L0020: ret

C.Get2()
    L0000: sub rsp, 0x28
    L0004: mov rax, [rcx+8]
    L0008: cmp dword ptr [rax+8], 0
    L000c: jbe short L0017
    L000e: mov rax, [rax+0x10]
    L0012: add rsp, 0x28
    L0016: ret
    L0017: call 0x00007ffaffa6ec10
    L001c: int3

SharpLab

Author: stephentoub
Assignees: -
Labels:

area-CodeGen-coreclr, untriaged

Milestone: -

@EgorBo EgorBo self-assigned this Feb 23, 2022
@EgorBo EgorBo added this to the 7.0.0 milestone Feb 23, 2022
@EgorBo EgorBo removed the untriaged New issue has not been triaged by the area owner label Feb 23, 2022
@EgorBo
Copy link
Member

EgorBo commented Feb 23, 2022

Not related: we should make CastHelpers inlineable (for really hot paths) e.g. LdelemaRef

@jkotas
Copy link
Member

jkotas commented Feb 23, 2022

From my understanding CORINFO_HELP_LDELEMA_REF can be eliminated if it's followed by dereference (IND)

ldelema does type check. It can be eliminated if you can reason about the exact type of the array. In this specific example, the JIT needs to take advantage of the fact that C is sealed and the array type is C[] and thus the type check is guaranteed to succeed. If C was not sealed, the type check can fail - for example:

using System;
using System.Threading;

public class C
{
    private readonly C[] _array = new D[1];
    
    public C Get1() => Volatile.Read(ref _array[0]);
    
    static void Main() { new C().Get1(); }
}

public class D : C { }

@EgorBo
Copy link
Member

EgorBo commented Feb 23, 2022

Sure! Good pont.
Worth noting that even for the following case we currently also end up with an ldelema helper:

public sealed class C
{
    private readonly C[] _array;
    
    public C Get2()
    {
        ref C c = ref _array[0];
        return c;
    }
}

it also forward-substituted to IND(CORINFO_HELP_LDELEMA_REF)

@ghost ghost added in-pr There is an active PR which will close this issue when it is merged and removed in-pr There is an active PR which will close this issue when it is merged labels Feb 24, 2022
@EgorBo EgorBo modified the milestones: 7.0.0, 8.0.0 May 30, 2022
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Apr 24, 2023
@ghost ghost locked as resolved and limited conversation to collaborators May 25, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI in-pr There is an active PR which will close this issue when it is merged
Projects
None yet
3 participants