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

JIT: Block morphing does not handle that decomposed writes can affect the destination #85874

Closed
jakobbotsch opened this issue May 6, 2023 · 1 comment · Fixed by #85887
Closed
Assignees
Labels
area-CodeGen-coreclr CLR JIT compiler in src/coreclr/src/jit and related components such as SuperPMI
Milestone

Comments

@jakobbotsch
Copy link
Member

[MethodImpl(MethodImplOptions.NoInlining)]
static int Test()
{
    S s;
    s.Me = &s;
    S s2;
    s2.Me = null;
    s2.F = 1234;
    *(S*)s.Me = s2;
    return s.F;
}

public unsafe struct S
{
    public void* Me;
    public int F;
}

Test returns 1234 in tier-0 but throws NullReferenceException in tier-1. Block morphing produces

MorphCopyBlock:
PrepareDst for [000021] have not found a local var.
block assignment to morph:
               [000022] -A-XG------                           ASG       struct (copy)
               [000021] ---XG+-N---                         ├──▌  BLK       struct<Program+S, 16>
               [000019] ----G+-----                           └──▌  LCL_VAR   long  (AX) V03 tmp1         
               [000020] -----+-----                         └──▌  LCL_VAR   struct<Program+S, 16>(P) V01 loc1         
                                                            └──▌    long   V01.Program+S:Me (offs=0x00) -> V05 tmp3          (last use)
                                                            └──▌    int    V01.Program+S:F (offs=0x08) -> V06 tmp4          (last use)
 (m_srcDoFldAsg=true) using field by field assignments.
dstAddr - Multiple Fields Clone created:
               [000033] ----G------                           LCL_VAR   long  (AX) V03 tmp1         
MorphCopyBlock (after):
               [000038] -A-XG+-----                           COMMA     void  
               [000031] -A-XG------                         ├──▌  ASG       long  
               [000030] ---XG--N---                           ├──▌  IND       long  
               [000019] ----G+-----                             └──▌  LCL_VAR   long  (AX) V03 tmp1         
               [000029] -----------                           └──▌  LCL_VAR   long   V05 tmp3         
               [000037] -A-XG------                         └──▌  ASG       int   
               [000036] ---XG--N---                            ├──▌  IND       int   
               [000035] ----G------                              └──▌  ADD       byref 
               [000033] ----G+-----                                 ├──▌  LCL_VAR   long  (AX) V03 tmp1         
               [000034] -----------                                 └──▌  CNS_INT   long   8
               [000032] -----------                            └──▌  LCL_VAR   int    V06 tmp4         

The first store overrides V03 that is also used in the second store.

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

ghost commented May 6, 2023

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

Issue Details
[MethodImpl(MethodImplOptions.NoInlining)]
static int Test()
{
    S s;
    s.Me = &s;
    S s2;
    s2.Me = null;
    s2.F = 1234;
    *(S*)s.Me = s2;
    return s.F;
}

public unsafe struct S
{
    public void* Me;
    public int F;
}

Test returns 1234 in tier-0 but throws NullReferenceException in tier-1. Block morphing produces

MorphCopyBlock:
PrepareDst for [000021] have not found a local var.
block assignment to morph:
               [000022] -A-XG------                           ASG       struct (copy)
               [000021] ---XG+-N---                         ├──▌  BLK       struct<Program+S, 16>
               [000019] ----G+-----                           └──▌  LCL_VAR   long  (AX) V03 tmp1         
               [000020] -----+-----                         └──▌  LCL_VAR   struct<Program+S, 16>(P) V01 loc1         
                                                            └──▌    long   V01.Program+S:Me (offs=0x00) -> V05 tmp3          (last use)
                                                            └──▌    int    V01.Program+S:F (offs=0x08) -> V06 tmp4          (last use)
 (m_srcDoFldAsg=true) using field by field assignments.
dstAddr - Multiple Fields Clone created:
               [000033] ----G------                           LCL_VAR   long  (AX) V03 tmp1         
MorphCopyBlock (after):
               [000038] -A-XG+-----                           COMMA     void  
               [000031] -A-XG------                         ├──▌  ASG       long  
               [000030] ---XG--N---                           ├──▌  IND       long  
               [000019] ----G+-----                             └──▌  LCL_VAR   long  (AX) V03 tmp1         
               [000029] -----------                           └──▌  LCL_VAR   long   V05 tmp3         
               [000037] -A-XG------                         └──▌  ASG       int   
               [000036] ---XG--N---                            ├──▌  IND       int   
               [000035] ----G------                              └──▌  ADD       byref 
               [000033] ----G+-----                                 ├──▌  LCL_VAR   long  (AX) V03 tmp1         
               [000034] -----------                                 └──▌  CNS_INT   long   8
               [000032] -----------                            └──▌  LCL_VAR   int    V06 tmp4         

The first store overrides V03 that is also used in the second store.

Author: jakobbotsch
Assignees: -
Labels:

area-CodeGen-coreclr, untriaged

Milestone: -

jakobbotsch added a commit to jakobbotsch/runtime that referenced this issue May 7, 2023
Fix a couple of cases where it's possible that the decomposed stores
will modify the address being used as part of the operation too early.
In those cases we must spill the address to a new local ahead of time.

Fix dotnet#85874
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label May 7, 2023
@jakobbotsch jakobbotsch self-assigned this May 7, 2023
@jakobbotsch jakobbotsch added this to the 8.0.0 milestone May 7, 2023
@jakobbotsch jakobbotsch removed the untriaged New issue has not been triaged by the area owner label May 7, 2023
jakobbotsch added a commit that referenced this issue May 9, 2023
Fix a couple of cases where it's possible that the decomposed stores
will modify the address being used as part of the operation too early.
In those cases we must spill the address to a new local ahead of time.

Fix #85874
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label May 9, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Jun 8, 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
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant