dotnet / runtime

.NET is a cross-platform runtime for cloud, mobile, desktop, and IoT apps.
https://docs.microsoft.com/dotnet/core/
MIT License
15.08k stars 4.69k forks source link

Optimized C# compilation code generates wrong values #47748

Closed ryanheath closed 3 years ago

ryanheath commented 3 years ago

Configuration

Description

We encountered a bug in optimized code generation, the code produces wrong results, however, when the NoOptimization attribute is applied, the code produces the correct results. Unfortunately, we cannot reproduce the bug on its own. We'll provide the piece of source code, the optimized and no-optimized disassembly of the source.

The piece of code

private static DateTime GetMaturityDateBondFromPositionData(ViewPosition position, DateTime reportDate, PrivateDebtDetail privateDebtDetail)
{
    if (privateDebtDetail != null)
    {
        return privateDebtDetail.OptionalityIndicator == 1 ? privateDebtDetail.ExpectedMaturityDate : position.MaturityDate.Value;
    }

    if (position.SectorLevel3.ToLower() == "securitized" || (position.RedemptionType ?? "none").ToLower() == "pension annuity")
    {
        return reportDate.AddDays(Math.Round((position.WeightedAverageLife ?? 1) * 365));
    }

    return position.FirstCallDate ?? (position.MaturityDate ?? throw new MissingDataException($"Maturity Date missing for Bond with Id {position.Id}"));
}

For example, when this function is called with:

the returned value is 0001-01-04 00:52:06 while it should have been 2021-01-18 00:00

See below the disassembly of the same code piece. We don't really see differences apart from addresses and optimized away method calls.

Disassembly of optimized code generation

        private static DateTime GetMaturityDateBondFromPositionData(ViewPosition position, DateTime reportDate, PrivateDebtDetail privateDebtDetail)
        {
            if (privateDebtDetail != null)
00007FFF5F3A50B0  push        rbp  
00007FFF5F3A50B1  sub         rsp,0C0h  
00007FFF5F3A50B8  vzeroupper  
00007FFF5F3A50BB  lea         rbp,[rsp+0C0h]  
00007FFF5F3A50C3  vxorps      xmm4,xmm4,xmm4  
00007FFF5F3A50C7  vmovdqa     xmmword ptr [rbp-0A0h],xmm4  
00007FFF5F3A50CF  mov         rax,0FFFFFFFFFFFFFF70h  
00007FFF5F3A50D9  vmovdqa     xmmword ptr [rax+rbp],xmm4  
00007FFF5F3A50DE  vmovdqa     xmmword ptr [rbp+rax+10h],xmm4  
00007FFF5F3A50E4  vmovdqa     xmmword ptr [rbp+rax+20h],xmm4  
00007FFF5F3A50EA  add         rax,30h  
00007FFF5F3A50EE  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+029h (07FFF5F3A50D9h)  
00007FFF5F3A50F0  mov         qword ptr [rbp+10h],rcx  
00007FFF5F3A50F4  mov         qword ptr [rbp+18h],rdx  
00007FFF5F3A50F8  mov         qword ptr [rbp+20h],r8  
00007FFF5F3A50FC  cmp         qword ptr [rbp+20h],0  
00007FFF5F3A5101  je          V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+098h (07FFF5F3A5148h)  
            {
                return privateDebtDetail.OptionalityIndicator == 1 ? privateDebtDetail.ExpectedMaturityDate : position.MaturityDate.Value;
00007FFF5F3A5103  mov         rcx,qword ptr [rbp+20h]  
00007FFF5F3A5107  cmp         dword ptr [rcx],ecx  
00007FFF5F3A5109  call        CLRStub[MethodDescPrestub]@7fff5c5c03b8 (07FFF5C5C03B8h)  
00007FFF5F3A510E  cmp         eax,1  
00007FFF5F3A5111  je          V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+084h (07FFF5F3A5134h)  
00007FFF5F3A5113  lea         rdx,[rbp-10h]  
00007FFF5F3A5117  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F3A511B  cmp         dword ptr [rcx],ecx  
00007FFF5F3A511D  call        CLRStub[MethodDescPrestub]@7fff5c5c4c68 (07FFF5C5C4C68h)  
00007FFF5F3A5122  lea         rcx,[rbp-10h]  
00007FFF5F3A5126  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].get_Value() (07FFF5B2B7A68h)  
00007FFF5F3A512B  mov         qword ptr [rbp-78h],rax  
00007FFF5F3A512F  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F3A5344h)  
00007FFF5F3A5134  mov         rcx,qword ptr [rbp+20h]  
00007FFF5F3A5138  cmp         dword ptr [rcx],ecx  
00007FFF5F3A513A  call        CLRStub[MethodDescPrestub]@7fff5c5c03c8 (07FFF5C5C03C8h)  
00007FFF5F3A513F  mov         qword ptr [rbp-78h],rax  
00007FFF5F3A5143  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F3A5344h)  
            }

            if (position.SectorLevel3.ToLower() == "securitized" || (position.RedemptionType ?? "none").ToLower() == "pension annuity")
00007FFF5F3A5148  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F3A514C  cmp         dword ptr [rcx],ecx  
00007FFF5F3A514E  call        Method stub for: V.A.D.M.A.ViewPosition.get_SectorLevel3() (07FFF5C5C4978h)  
00007FFF5F3A5153  mov         rcx,rax  
00007FFF5F3A5156  cmp         dword ptr [rcx],ecx  
00007FFF5F3A5158  call        Method stub for: System.String.ToLower() (07FFF5B2955A0h)  
00007FFF5F3A515D  mov         qword ptr [rbp-80h],rax  
00007FFF5F3A5161  mov         rcx,qword ptr [rbp-80h]  
00007FFF5F3A5165  mov         rdx,21D97563308h  
00007FFF5F3A516F  mov         rdx,qword ptr [rdx]  
00007FFF5F3A5172  call        Method stub for: System.String.op_Equality(System.String, System.String) (07FFF5B295B60h)  
00007FFF5F3A5177  test        eax,eax  
00007FFF5F3A5179  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+012Dh (07FFF5F3A51DDh)  
00007FFF5F3A517B  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F3A517F  cmp         dword ptr [rcx],ecx  
00007FFF5F3A5181  call        CLRStub[MethodDescPrestub]@7fff5c5c48c8 (07FFF5C5C48C8h)  
00007FFF5F3A5186  mov         qword ptr [rbp-58h],rax  
00007FFF5F3A518A  mov         rcx,qword ptr [rbp-58h]  
00007FFF5F3A518E  mov         qword ptr [rbp-60h],rcx  
00007FFF5F3A5192  cmp         qword ptr [rbp-58h],0  
00007FFF5F3A5197  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0FAh (07FFF5F3A51AAh)  
00007FFF5F3A5199  mov         rcx,21D97563310h  
00007FFF5F3A51A3  mov         rcx,qword ptr [rcx]  
00007FFF5F3A51A6  mov         qword ptr [rbp-60h],rcx  
00007FFF5F3A51AA  mov         rcx,qword ptr [rbp-60h]  
00007FFF5F3A51AE  cmp         dword ptr [rcx],ecx  
00007FFF5F3A51B0  call        Method stub for: System.String.ToLower() (07FFF5B2955A0h)  
00007FFF5F3A51B5  mov         qword ptr [rbp-88h],rax  
00007FFF5F3A51BC  mov         rcx,qword ptr [rbp-88h]  
00007FFF5F3A51C3  mov         rdx,21D97563318h  
00007FFF5F3A51CD  mov         rdx,qword ptr [rdx]  
00007FFF5F3A51D0  call        Method stub for: System.String.op_Equality(System.String, System.String) (07FFF5B295B60h)  
00007FFF5F3A51D5  test        eax,eax  
00007FFF5F3A51D7  je          V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+01B2h (07FFF5F3A5262h)  
            {
                return reportDate.AddDays(Math.Round((position.WeightedAverageLife ?? 1) * 365));
00007FFF5F3A51DD  lea         rdx,[rbp-20h]  
00007FFF5F3A51E1  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F3A51E5  cmp         dword ptr [rcx],ecx  
00007FFF5F3A51E7  call        CLRStub[MethodDescPrestub]@7fff5c5c46c8 (07FFF5C5C46C8h)  
00007FFF5F3A51EC  lea         rcx,[rbp+18h]  
00007FFF5F3A51F0  mov         qword ptr [rbp-40h],rcx  
00007FFF5F3A51F4  lea         rcx,[rbp-20h]  
00007FFF5F3A51F8  call        CLRStub[MethodDescPrestub]@7fff5b7eea60 (07FFF5B7EEA60h)  
00007FFF5F3A51FD  test        eax,eax  
00007FFF5F3A51FF  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0168h (07FFF5F3A5218h)  
00007FFF5F3A5201  mov         rcx,qword ptr [rbp-40h]  
00007FFF5F3A5205  mov         qword ptr [rbp-48h],rcx  
00007FFF5F3A5209  vmovsd      xmm0,qword ptr [V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+02B8h (07FFF5F3A5368h)]  
00007FFF5F3A5211  vmovsd      qword ptr [rbp-50h],xmm0  
00007FFF5F3A5216  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+017Eh (07FFF5F3A522Eh)  
00007FFF5F3A5218  mov         rcx,qword ptr [rbp-40h]  
00007FFF5F3A521C  mov         qword ptr [rbp-48h],rcx  
00007FFF5F3A5220  lea         rcx,[rbp-20h]  
00007FFF5F3A5224  call        Method stub for: System.Nullable`1[[System.Double, System.Private.CoreLib]].GetValueOrDefault() (07FFF5B7EEA70h)  
00007FFF5F3A5229  vmovsd      qword ptr [rbp-50h],xmm0  
00007FFF5F3A522E  vmovsd      xmm0,qword ptr [rbp-50h]  
00007FFF5F3A5233  vmulsd      xmm0,xmm0,mmword ptr [V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+02C8h (07FFF5F3A5378h)]  
00007FFF5F3A523B  call        CLRStub[MethodDescPrestub]@7fff5d378be8 (07FFF5D378BE8h)  
00007FFF5F3A5240  vmovsd      qword ptr [rbp-90h],xmm0  
00007FFF5F3A5248  vmovsd      xmm1,qword ptr [rbp-90h]  
00007FFF5F3A5250  mov         rcx,qword ptr [rbp-48h]  
00007FFF5F3A5254  call        CLRStub[MethodDescPrestub]@7fff5b2b5cc8 (07FFF5B2B5CC8h)  
00007FFF5F3A5259  mov         qword ptr [rbp-78h],rax  
00007FFF5F3A525D  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F3A5344h)  
            }

            return position.FirstCallDate ?? (position.MaturityDate ?? throw new MissingDataException($"Maturity Date missing for Bond with Id {position.Id}"));
00007FFF5F3A5262  lea         rdx,[rbp-10h]  
00007FFF5F3A5266  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F3A526A  cmp         dword ptr [rcx],ecx  
00007FFF5F3A526C  call        CLRStub[MethodDescPrestub]@7fff5c5c4fb8 (07FFF5C5C4FB8h)  
00007FFF5F3A5271  lea         rcx,[rbp-10h]  
00007FFF5F3A5275  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].get_HasValue() (07FFF5B2B7A60h)  
00007FFF5F3A527A  test        eax,eax  
00007FFF5F3A527C  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0285h (07FFF5F3A5335h)  
00007FFF5F3A5282  lea         rdx,[rbp-30h]  
00007FFF5F3A5286  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F3A528A  cmp         dword ptr [rcx],ecx  
00007FFF5F3A528C  call        CLRStub[MethodDescPrestub]@7fff5c5c4c68 (07FFF5C5C4C68h)  
00007FFF5F3A5291  lea         rcx,[rbp-30h]  
00007FFF5F3A5295  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].get_HasValue() (07FFF5B2B7A60h)  
00007FFF5F3A529A  test        eax,eax  
00007FFF5F3A529C  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0276h (07FFF5F3A5326h)  
00007FFF5F3A52A2  mov         rcx,7FFF5B26C5D8h  
00007FFF5F3A52AC  call        CORINFO_HELP_NEWSFAST (07FFFBADFA370h)  
00007FFF5F3A52B1  mov         qword ptr [rbp-68h],rax  
00007FFF5F3A52B5  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F3A52B9  cmp         dword ptr [rcx],ecx  
00007FFF5F3A52BB  call        Method stub for: V.A.D.M.A.ViewPosition.get_Id() (07FFF5C5C4748h)  
00007FFF5F3A52C0  mov         rcx,qword ptr [rbp-68h]  
00007FFF5F3A52C4  mov         qword ptr [rcx+8],rax  
00007FFF5F3A52C8  mov         rcx,7FFF5D783BB0h  
00007FFF5F3A52D2  call        CORINFO_HELP_NEWSFAST (07FFFBADFA370h)  
00007FFF5F3A52D7  mov         qword ptr [rbp-70h],rax  
00007FFF5F3A52DB  mov         ecx,2A8Ch  
00007FFF5F3A52E0  mov         rdx,7FFF5BA9E718h  
00007FFF5F3A52EA  call        00007FFFBAD00B70  
00007FFF5F3A52EF  mov         qword ptr [rbp-98h],rax  
00007FFF5F3A52F6  mov         rcx,qword ptr [rbp-98h]  
00007FFF5F3A52FD  mov         rdx,qword ptr [rbp-68h]  
00007FFF5F3A5301  call        CLRStub[MethodDescPrestub]@7fff5b295930 (07FFF5B295930h)  
00007FFF5F3A5306  mov         qword ptr [rbp-0A0h],rax  
00007FFF5F3A530D  mov         rdx,qword ptr [rbp-0A0h]  
00007FFF5F3A5314  mov         rcx,qword ptr [rbp-70h]  
00007FFF5F3A5318  call        CLRStub[MethodDescPrestub]@7fff5d378f88 (07FFF5D378F88h)  
00007FFF5F3A531D  mov         rcx,qword ptr [rbp-70h]  
00007FFF5F3A5321  call        00007FFFBADD0B10  
00007FFF5F3A5326  lea         rcx,[rbp-30h]  
00007FFF5F3A532A  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].GetValueOrDefault() (07FFF5B2B7A70h)  
00007FFF5F3A532F  mov         qword ptr [rbp-78h],rax  
00007FFF5F3A5333  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F3A5344h)  
00007FFF5F3A5335  lea         rcx,[rbp-10h]  
00007FFF5F3A5339  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].GetValueOrDefault() (07FFF5B2B7A70h)  
00007FFF5F3A533E  mov         qword ptr [rbp-78h],rax  
00007FFF5F3A5342  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F3A5344h)  
00007FFF5F3A5344  mov         rax,qword ptr [rbp-78h]  
00007FFF5F3A5348  lea         rsp,[rbp]  
00007FFF5F3A534C  pop         rbp  
00007FFF5F3A534D  ret  
00007FFF5F3A534E  int         3  
00007FFF5F3A534F  int         3  
00007FFF5F3A5350  int         3  
00007FFF5F3A5351  int         3  
00007FFF5F3A5352  int         3  
00007FFF5F3A5353  int         3  
00007FFF5F3A5354  int         3  
00007FFF5F3A5355  int         3  
00007FFF5F3A5356  int         3  
00007FFF5F3A5357  int         3  
00007FFF5F3A5358  int         3  
00007FFF5F3A5359  int         3  
00007FFF5F3A535A  add         byte ptr [rax],al  
00007FFF5F3A535C  add         byte ptr [rax],al  
00007FFF5F3A535E  add         byte ptr [rax],al  
00007FFF5F3A5360  add         byte ptr [rax],al  
00007FFF5F3A5362  add         byte ptr [rax],al  
00007FFF5F3A5364  add         byte ptr [rax],al  
00007FFF5F3A5366  add         byte ptr [rax],al  
00007FFF5F3A5368  add         byte ptr [rax],al  
00007FFF5F3A536A  add         byte ptr [rax],al  
00007FFF5F3A536C  add         byte ptr [rax],al  
00007FFF5F3A536E  ?? ?????? 
00007FFF5F3A536F  ?? ?????? 
            }

            return position.FirstCallDate ?? (position.MaturityDate ?? throw new MissingDataException($"Maturity Date missing for Bond with Id {position.Id}"));
00007FFF5F3A5370  add         byte ptr [rax],al  
00007FFF5F3A5372  add         byte ptr [rax],al  
00007FFF5F3A5374  add         byte ptr [rax],al  
00007FFF5F3A5376  add         byte ptr [rax],al  
00007FFF5F3A5378  add         byte ptr [rax],al  
00007FFF5F3A537A  add         byte ptr [rax],al  
00007FFF5F3A537C  add         al,dl  
00007FFF5F3A537E  jbe         00007FFF5F3A53C0  
00007FFF5F3A5380  sbb         dword ptr [rax],ecx  
00007FFF5F3A5382  add         eax,dword ptr [rax]  
00007FFF5F3A5384  or          byte ptr [rcx],al  
00007FFF5F3A5386  sbb         byte ptr [rax],al  
00007FFF5F3A5388  add         dword ptr [rax],edx  
00007FFF5F3A538B  add         byte ptr [rax],al  
00007FFF5F3A538E  add         byte ptr [rax],al  
00007FFF5F3A5390  ?? ?????? 

Disassembly of noOptimized code generation

        [MethodImpl(MethodImplOptions.NoOptimization)]
        private static DateTime GetMaturityDateBondFromPositionData(ViewPosition position, DateTime reportDate, PrivateDebtDetail privateDebtDetail)
        {
            if (privateDebtDetail != null)
00007FFF5F366D00  push        rbp  
00007FFF5F366D01  sub         rsp,0C0h  
00007FFF5F366D08  vzeroupper  
00007FFF5F366D0B  lea         rbp,[rsp+0C0h]  
00007FFF5F366D13  vxorps      xmm4,xmm4,xmm4  
00007FFF5F366D17  vmovdqa     xmmword ptr [rbp-0A0h],xmm4  
00007FFF5F366D1F  mov         rax,0FFFFFFFFFFFFFF70h  
00007FFF5F366D29  vmovdqa     xmmword ptr [rax+rbp],xmm4  
00007FFF5F366D2E  vmovdqa     xmmword ptr [rbp+rax+10h],xmm4  
00007FFF5F366D34  vmovdqa     xmmword ptr [rbp+rax+20h],xmm4  
00007FFF5F366D3A  add         rax,30h  
00007FFF5F366D3E  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+029h (07FFF5F366D29h)  
00007FFF5F366D40  mov         qword ptr [rbp+10h],rcx  
00007FFF5F366D44  mov         qword ptr [rbp+18h],rdx  
00007FFF5F366D48  mov         qword ptr [rbp+20h],r8  
00007FFF5F366D4C  cmp         qword ptr [rbp+20h],0  
00007FFF5F366D51  je          V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+098h (07FFF5F366D98h)  
            {
                return privateDebtDetail.OptionalityIndicator == 1 ? privateDebtDetail.ExpectedMaturityDate : position.MaturityDate.Value;
00007FFF5F366D53  mov         rcx,qword ptr [rbp+20h]  
00007FFF5F366D57  cmp         dword ptr [rcx],ecx  
00007FFF5F366D59  call        CLRStub[MethodDescPrestub]@7fff5c545390 (07FFF5C545390h)  
00007FFF5F366D5E  cmp         eax,1  
00007FFF5F366D61  je          V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+084h (07FFF5F366D84h)  
00007FFF5F366D63  lea         rdx,[rbp-10h]  
00007FFF5F366D67  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F366D6B  cmp         dword ptr [rcx],ecx  
00007FFF5F366D6D  call        Method stub for: V.A.D.M.A.ViewPosition.get_MaturityDate() (07FFF5C54A4A0h)  
00007FFF5F366D72  lea         rcx,[rbp-10h]  
00007FFF5F366D76  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].get_Value() (07FFF5B2C7A88h)  
00007FFF5F366D7B  mov         qword ptr [rbp-78h],rax  
00007FFF5F366D7F  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F366F94h)  
00007FFF5F366D84  mov         rcx,qword ptr [rbp+20h]  
00007FFF5F366D88  cmp         dword ptr [rcx],ecx  
00007FFF5F366D8A  call        CLRStub[MethodDescPrestub]@7fff5c5453a0 (07FFF5C5453A0h)  
00007FFF5F366D8F  mov         qword ptr [rbp-78h],rax  
00007FFF5F366D93  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F366F94h)  
            }

            if (position.SectorLevel3.ToLower() == "securitized" || (position.RedemptionType ?? "none").ToLower() == "pension annuity")
00007FFF5F366D98  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F366D9C  cmp         dword ptr [rcx],ecx  
00007FFF5F366D9E  call        Method stub for: V.A.D.M.A.ViewPosition.get_SectorLevel3() (07FFF5C54A1B0h)  
00007FFF5F366DA3  mov         rcx,rax  
00007FFF5F366DA6  cmp         dword ptr [rcx],ecx  
00007FFF5F366DA8  call        Method stub for: System.String.ToLower() (07FFF5B2A55A0h)  
00007FFF5F366DAD  mov         qword ptr [rbp-80h],rax  
00007FFF5F366DB1  mov         rcx,qword ptr [rbp-80h]  
00007FFF5F366DB5  mov         rdx,1DE0F7C4688h  
00007FFF5F366DBF  mov         rdx,qword ptr [rdx]  
00007FFF5F366DC2  call        Method stub for: System.String.op_Equality(System.String, System.String) (07FFF5B2A5B60h)  
00007FFF5F366DC7  test        eax,eax  
00007FFF5F366DC9  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+012Dh (07FFF5F366E2Dh)  
00007FFF5F366DCB  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F366DCF  cmp         dword ptr [rcx],ecx  
00007FFF5F366DD1  call        Method stub for: V.A.D.M.A.ViewPosition.get_RedemptionType() (07FFF5C54A100h)  
00007FFF5F366DD6  mov         qword ptr [rbp-58h],rax  
00007FFF5F366DDA  mov         rcx,qword ptr [rbp-58h]  
00007FFF5F366DDE  mov         qword ptr [rbp-60h],rcx  
00007FFF5F366DE2  cmp         qword ptr [rbp-58h],0  
00007FFF5F366DE7  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0FAh (07FFF5F366DFAh)  
00007FFF5F366DE9  mov         rcx,1DE0F7C4690h  
00007FFF5F366DF3  mov         rcx,qword ptr [rcx]  
00007FFF5F366DF6  mov         qword ptr [rbp-60h],rcx  
00007FFF5F366DFA  mov         rcx,qword ptr [rbp-60h]  
00007FFF5F366DFE  cmp         dword ptr [rcx],ecx  
00007FFF5F366E00  call        Method stub for: System.String.ToLower() (07FFF5B2A55A0h)  
00007FFF5F366E05  mov         qword ptr [rbp-88h],rax  
00007FFF5F366E0C  mov         rcx,qword ptr [rbp-88h]  
00007FFF5F366E13  mov         rdx,1DE0F7C4698h  
00007FFF5F366E1D  mov         rdx,qword ptr [rdx]  
00007FFF5F366E20  call        Method stub for: System.String.op_Equality(System.String, System.String) (07FFF5B2A5B60h)  
00007FFF5F366E25  test        eax,eax  
00007FFF5F366E27  je          V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+01B2h (07FFF5F366EB2h)  
            {
                return reportDate.AddDays(Math.Round((position.WeightedAverageLife ?? 1) * 365));
00007FFF5F366E2D  lea         rdx,[rbp-20h]  
00007FFF5F366E31  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F366E35  cmp         dword ptr [rcx],ecx  
00007FFF5F366E37  call        Method stub for: V.A.D.M.A.ViewPosition.get_WeightedAverageLife() (07FFF5C549FA8h)  
00007FFF5F366E3C  lea         rcx,[rbp+18h]  
00007FFF5F366E40  mov         qword ptr [rbp-40h],rcx  
00007FFF5F366E44  lea         rcx,[rbp-20h]  
00007FFF5F366E48  call        Method stub for: System.Nullable`1[[System.Double, System.Private.CoreLib]].get_HasValue() (07FFF5B7ECF50h)  
00007FFF5F366E4D  test        eax,eax  
00007FFF5F366E4F  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0168h (07FFF5F366E68h)  
00007FFF5F366E51  mov         rcx,qword ptr [rbp-40h]  
00007FFF5F366E55  mov         qword ptr [rbp-48h],rcx  
00007FFF5F366E59  vmovsd      xmm0,qword ptr [V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+02B8h (07FFF5F366FB8h)]  
00007FFF5F366E61  vmovsd      qword ptr [rbp-50h],xmm0  
00007FFF5F366E66  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+017Eh (07FFF5F366E7Eh)  
00007FFF5F366E68  mov         rcx,qword ptr [rbp-40h]  
00007FFF5F366E6C  mov         qword ptr [rbp-48h],rcx  
00007FFF5F366E70  lea         rcx,[rbp-20h]  
00007FFF5F366E74  call        Method stub for: System.Nullable`1[[System.Double, System.Private.CoreLib]].GetValueOrDefault() (07FFF5B7ECF60h)  
00007FFF5F366E79  vmovsd      qword ptr [rbp-50h],xmm0  
00007FFF5F366E7E  vmovsd      xmm0,qword ptr [rbp-50h]  
00007FFF5F366E83  vmulsd      xmm0,xmm0,mmword ptr [V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+02C8h (07FFF5F366FC8h)]  
00007FFF5F366E8B  call        Method stub for: V.A.L.Math.Round(Double) (07FFF5D3E9120h)  
00007FFF5F366E90  vmovsd      qword ptr [rbp-90h],xmm0  
00007FFF5F366E98  vmovsd      xmm1,qword ptr [rbp-90h]  
00007FFF5F366EA0  mov         rcx,qword ptr [rbp-48h]  
00007FFF5F366EA4  call        Method stub for: System.DateTime.AddDays(Double) (07FFF5B2C5E50h)  
00007FFF5F366EA9  mov         qword ptr [rbp-78h],rax  
00007FFF5F366EAD  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F366F94h)  
            }

            return position.FirstCallDate ?? (position.MaturityDate ?? throw new MissingDataException($"Maturity Date missing for Bond with Id {position.Id}"));
00007FFF5F366EB2  lea         rdx,[rbp-10h]  
00007FFF5F366EB6  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F366EBA  cmp         dword ptr [rcx],ecx  
00007FFF5F366EBC  call        Method stub for: V.A.D.M.A.ViewPosition.get_FirstCallDate() (07FFF5C54A7F0h)  
00007FFF5F366EC1  lea         rcx,[rbp-10h]  
00007FFF5F366EC5  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].get_HasValue() (07FFF5B2C7A80h)  
00007FFF5F366ECA  test        eax,eax  
00007FFF5F366ECC  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0285h (07FFF5F366F85h)  
00007FFF5F366ED2  lea         rdx,[rbp-30h]  
00007FFF5F366ED6  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F366EDA  cmp         dword ptr [rcx],ecx  
00007FFF5F366EDC  call        Method stub for: V.A.D.M.A.ViewPosition.get_MaturityDate() (07FFF5C54A4A0h)  
00007FFF5F366EE1  lea         rcx,[rbp-30h]  
00007FFF5F366EE5  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].get_HasValue() (07FFF5B2C7A80h)  
00007FFF5F366EEA  test        eax,eax  
00007FFF5F366EEC  jne         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0276h (07FFF5F366F76h)  
00007FFF5F366EF2  mov         rcx,7FFF5B27C5D8h  
00007FFF5F366EFC  call        CORINFO_HELP_NEWSFAST (07FFFBADFA370h)  
00007FFF5F366F01  mov         qword ptr [rbp-68h],rax  
00007FFF5F366F05  mov         rcx,qword ptr [rbp+10h]  
00007FFF5F366F09  cmp         dword ptr [rcx],ecx  
00007FFF5F366F0B  call        Method stub for: V.A.D.M.A.ViewPosition.get_Id() (07FFF5C54A028h)  
00007FFF5F366F10  mov         rcx,qword ptr [rbp-68h]  
00007FFF5F366F14  mov         qword ptr [rcx+8],rax  
00007FFF5F366F18  mov         rcx,7FFF5D7F8578h  
00007FFF5F366F22  call        CORINFO_HELP_NEWSFAST (07FFFBADFA370h)  
00007FFF5F366F27  mov         qword ptr [rbp-70h],rax  
00007FFF5F366F2B  mov         ecx,2A8Ch  
00007FFF5F366F30  mov         rdx,7FFF5BAC97D8h  
00007FFF5F366F3A  call        00007FFFBAD00B70  
00007FFF5F366F3F  mov         qword ptr [rbp-98h],rax  
00007FFF5F366F46  mov         rcx,qword ptr [rbp-98h]  
00007FFF5F366F4D  mov         rdx,qword ptr [rbp-68h]  
00007FFF5F366F51  call        CLRStub[MethodDescPrestub]@7fff5b2a5930 (07FFF5B2A5930h)  
00007FFF5F366F56  mov         qword ptr [rbp-0A0h],rax  
00007FFF5F366F5D  mov         rdx,qword ptr [rbp-0A0h]  
00007FFF5F366F64  mov         rcx,qword ptr [rbp-70h]  
00007FFF5F366F68  call        CLRStub[MethodDescPrestub]@7fff5d3e94c0 (07FFF5D3E94C0h)  
00007FFF5F366F6D  mov         rcx,qword ptr [rbp-70h]  
00007FFF5F366F71  call        00007FFFBADD0B10  
00007FFF5F366F76  lea         rcx,[rbp-30h]  
00007FFF5F366F7A  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].GetValueOrDefault() (07FFF5B2C7A90h)  
00007FFF5F366F7F  mov         qword ptr [rbp-78h],rax  
00007FFF5F366F83  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F366F94h)  
00007FFF5F366F85  lea         rcx,[rbp-10h]  
00007FFF5F366F89  call        Method stub for: System.Nullable`1[[System.DateTime, System.Private.CoreLib]].GetValueOrDefault() (07FFF5B2C7A90h)  
00007FFF5F366F8E  mov         qword ptr [rbp-78h],rax  
00007FFF5F366F92  jmp         V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+0294h (07FFF5F366F94h)  
00007FFF5F366F94  mov         rax,qword ptr [rbp-78h]  
00007FFF5F366F98  lea         rsp,[rbp]  
00007FFF5F366F9C  pop         rbp  
00007FFF5F366F9D  ret  
00007FFF5F366F9E  int         3  
00007FFF5F366F9F  int         3  
00007FFF5F366FA0  int         3  
00007FFF5F366FA1  int         3  
00007FFF5F366FA2  int         3  
00007FFF5F366FA3  int         3  
00007FFF5F366FA4  int         3  
00007FFF5F366FA5  int         3  
00007FFF5F366FA6  int         3  
00007FFF5F366FA7  int         3  
00007FFF5F366FA8  int         3  
00007FFF5F366FA9  int         3  
00007FFF5F366FAA  add         byte ptr [rax],al  
00007FFF5F366FAC  add         byte ptr [rax],al  
00007FFF5F366FAE  add         byte ptr [rax],al  
00007FFF5F366FB0  add         byte ptr [rax],al  
00007FFF5F366FB2  add         byte ptr [rax],al  
00007FFF5F366FB4  add         byte ptr [rax],al  
00007FFF5F366FB6  add         byte ptr [rax],al  
00007FFF5F366FB8  add         byte ptr [rax],al  
00007FFF5F366FBA  add         byte ptr [rax],al  
00007FFF5F366FBC  add         byte ptr [rax],al  
00007FFF5F366FBE  ?? ?????? 
00007FFF5F366FBF  ?? ?????? 
            }

            return position.FirstCallDate ?? (position.MaturityDate ?? throw new MissingDataException($"Maturity Date missing for Bond with Id {position.Id}"));
00007FFF5F366FC0  add         byte ptr [rax],al  
00007FFF5F366FC2  add         byte ptr [rax],al  
00007FFF5F366FC4  add         byte ptr [rax],al  
00007FFF5F366FC6  add         byte ptr [rax],al  
00007FFF5F366FC8  add         byte ptr [rax],al  
00007FFF5F366FCA  add         byte ptr [rax],al  
00007FFF5F366FCC  add         al,dl  
00007FFF5F366FCE  jbe         V.A.D.M.A.ViewPosition.get_RedemptionType()+020h (07FFF5F367010h)  
00007FFF5F366FD0  sbb         dword ptr [rax],ecx  
00007FFF5F366FD2  add         eax,dword ptr [rax]  
00007FFF5F366FD4  or          byte ptr [rcx],al  
00007FFF5F366FD6  sbb         byte ptr [rax],al  
00007FFF5F366FD8  add         dword ptr [rax],edx  
00007FFF5F366FDB  add         byte ptr [rax],al  
00007FFF5F366FDE  add         byte ptr [rax],al  
00007FFF5F366FE0  add         byte ptr [rax],al  
00007FFF5F366FE2  add         byte ptr [rax],al  
00007FFF5F366FE4  add         byte ptr [rax],al  
00007FFF5F366FE6  add         byte ptr [rax],al  
00007FFF5F366FE8  shr         cl,1  
00007FFF5F366FEA  pop         di  
00007FFF5F366FEC  ?? ?????? 
            }

            return position.FirstCallDate ?? (position.MaturityDate ?? throw new MissingDataException($"Maturity Date missing for Bond with Id {position.Id}"));
00007FFF5F366FED  jg          V.A.D.B.GetMaturityDateBondFromPositionData(V.A.D.M.A.ViewPosition, System.DateTime, V.A.D.M.A.PrivateDebtDetail)+02EFh (07FFF5F366FEFh)  
00007FFF5F366FEF  ?? ?????? 
EgorBo commented 3 years ago

@ryanheath Could you please create a self-contained repro (a console app with Main) because it's not clear what ViewPosition and PrivateDebtDetail are - are they structs? what layout, etc.

ryanheath commented 3 years ago

@EgorBo We have tried to localize the problem in a console app but the problem is not reproduced, not in debug mode, nor release mode, nor with added optimization attributes,

The ViewPosition class is large with lots of properties, see attached source. Program.txt

EgorBo commented 3 years ago

@ryalanms Thank you for the repro! Slightly more compact:

using System;
using System.Runtime.CompilerServices;

class Program
{
    static void Main()
    {
        Console.WriteLine(Test(null, DateTime.UtcNow, 42));
    }

    [MethodImpl(MethodImplOptions.NoInlining | 
                MethodImplOptions.AggressiveOptimization)]
    static DateTime Test(DateTime? date1, DateTime date2, int n)
    {
        if (date1 != null)
            return n == 1 ? date2 : date1.Value;

        if (n == 42)
            return date2;

        return date1 ?? date2;
    }
}

Under Debug:

2/2/2021 1:17:19 PM

Under Release:

1/1/0001 12:00:00 AM

Doesn't reproduce on netcoreapp3.1 so must be a 5.0 regression.

ryanheath commented 3 years ago

@EgorBo Great to see you succeed to reproduce it!

AndyAyersMS commented 3 years ago

@EgorBo can you investigate where things go wrong?

EgorBo commented 3 years ago

@AndyAyersMS sure!

EgorBo commented 3 years ago

@AndyAyersMS ah, actually it doesn't reproduce on master (and even on .NET6-preview1 binaries) - but does reproduce on .NET 5 (even 5.0.200) Do you want me to find the exact commit which fixed it (if we want to backport to .NET 5.0) ?

AndyAyersMS commented 3 years ago

Do you want me to find the exact commit which fixed ...

Yes. I think we'll want to fix this in 5.0.

Since you know which method has bad codegen, you can try diffing the 5.x and 6.x jit dumps to see where they diverge. That will likely pinpoint where the fix happened.

EgorBo commented 3 years ago

Do you want me to find the exact commit which fixed ...

Yes. I think we'll want to fix this in 5.0.

Since you know which method has bad codegen, you can try diffing the 5.x and 6.x jit dumps to see where they diverge. That will likely pinpoint where the fix happened.

I've bisected the problem and it turns out https://github.com/dotnet/runtime/pull/45134 fixed the issue - the ^ repro used to assert in Checked mode:

               [000054] -----+------              *  LCL_VAR   long   V07 tmp3

Assert failure(PID 23208 [0x00005aa8], Thread: 27944 [0x6d28]): Assertion failed '!"Incompatible types for gtNewTempAssign"' in 'Program:Test(System.Nullable`1[DateTime],System.DateTime,int):System.DateTime' during 'Morph - Global' (IL size 51)

    File: runtime-2\src\coreclr\jit\gentree.cpp Line: 15490
    Image: ConsoleApp11\ConsoleApp11\bin\Release\net5.0\win10-x64\ConsoleApp11.exe

Looks like the fix is already backported and should be available in .NET 5.0.3 https://github.com/dotnet/runtime/pull/45989

AndyAyersMS commented 3 years ago

Thanks Egor. Looks like 5.0.3 should be available in the next week or so.

@ryanheath when 5.0.3 is out, it would be great if you could verify that it fixes your full app.

ryanheath commented 3 years ago

Thanks @Egor! @AndyAyersMS I'll test it as soon as it comes out.

ryanheath commented 3 years ago

@EgorBo @AndyAyersMS The bug is fixed also at our end, thanks!