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 misses a zero extension in series of casts #55127

Closed
jakobbotsch opened this issue Jul 3, 2021 · 2 comments · Fixed by #55129
Closed

JIT misses a zero extension in series of casts #55127

jakobbotsch opened this issue Jul 3, 2021 · 2 comments · Fixed by #55129
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

// Generated by Fuzzlyn v1.2 on 2021-07-03 17:01:15
// Seed: 2766830457064421119
// Reduced from 188.7 KiB to 0.5 KiB in 00:03:34
// Debug: Outputs 4294967295
// Release: Outputs -1
public class Program
{
    static I s_i = new C();
    static short s_7;
    static sbyte[][] s_10 = new sbyte[][]{new sbyte[]{-1}};
    public static void Main()
    {
        var vr59 = (uint)M6(s_10[0][0]);
        System.Console.WriteLine((long)vr59);
    }

    static ulong M6(sbyte arg0)
    {
        return (ulong)arg0;
        ref short var1 = ref s_7;
        s_i.Foo(var1);
    }
}

interface I
{
    void Foo<T>(T val);
}

class C : I
{
    public void Foo<T>(T val) { }
}

We end up not doing any zero extension:

; Assembly listing for method Program:Main()
; Emitting BLENDED_CODE for X64 CPU with AVX - Windows
; optimized code
; rsp based frame
; partially interruptible
; No PGO data
; 0 inlinees with PGO data; 1 single block inlinees; 0 inlinees without PGO data
; Final local variable assignments
;
;  V00 OutArgs      [V00    ] (  1,  1   )  lclBlk (32) [rsp+00H]   "OutgoingArgSpace"
;  V01 tmp1         [V01,T03] (  2,  2   )    long  ->  rcx         "Inline return value spill temp"
;  V02 tmp2         [V02,T02] (  2,  4   )    byte  ->  rcx         "Inlining Arg"
;  V03 tmp3         [V03,T00] (  3,  6   )     ref  ->  rcx         "arr expr"
;  V04 tmp4         [V04,T01] (  3,  6   )     ref  ->  rcx         "arr expr"
;
; Lcl frame size = 40

G_M27646_IG01:              ;; offset=0000H
       4883EC28             sub      rsp, 40
                                                ;; bbWeight=1    PerfScore 0.25
G_M27646_IG02:              ;; offset=0004H
       48B92008A65FFE7F0000 mov      rcx, 0x7FFE5FA60820
       BA01000000           mov      edx, 1
       E80847A55F           call     CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE
       48B9582E001876020000 mov      rcx, 0x27618002E58
       488B09               mov      rcx, gword ptr [rcx]
       83790800             cmp      dword ptr [rcx+8], 0
       761D                 jbe      SHORT G_M27646_IG04
       488B4910             mov      rcx, gword ptr [rcx+16]
       83790800             cmp      dword ptr [rcx+8], 0
       7613                 jbe      SHORT G_M27646_IG04
       480FBE4910           movsx    rcx, byte  ptr [rcx+16]
       4863C9               movsxd   rcx, ecx
       E8D6FCFFFF           call     System.Console:WriteLine(long)
       90                   nop
                                                ;; bbWeight=1    PerfScore 15.25
G_M27646_IG03:              ;; offset=0043H
       4883C428             add      rsp, 40
       C3                   ret
                                                ;; bbWeight=1    PerfScore 1.25
G_M27646_IG04:              ;; offset=0048H
       E8E336765F           call     CORINFO_HELP_RNGCHKFAIL
       CC                   int3
                                                ;; bbWeight=0    PerfScore 0.00

; Total bytes of code 78, prolog size 4, PerfScore 24.55, instruction count 19, allocated bytes for code 78 (MethodHash=cb019401) for method Program:Main()
; ============================================================

It seems like things look ok all the way until code gen. We inline M6 and end up with:

***** BB01
STMT00006 (IL 0x015...  ???)
               [000043] -A----------              *  ASG       long  
               [000042] D------N----              +--*  LCL_VAR   long   V03 tmp2         
               [000041] ------------              \--*  CAST      long <- int
               [000040] ------------                 \--*  LCL_VAR   int    V04 tmp3         

***** BB01
STMT00009 (IL   ???...  ???)
               [000051] -AC---------              *  ASG       long  
               [000050] D------N----              +--*  LCL_VAR   long   V05 tmp4         
               [000037] --C------U--              \--*  CAST      long <- ulong <- uint
               [000036] --C---------                 \--*  CAST      int <- uint <- long
               [000044] ------------                    \--*  LCL_VAR   long   V03 tmp2         

***** BB01
STMT00008 (IL   ???...  ???)
               [000049] --C-G-------              *  CALL      void   System.Console.WriteLine
               [000048] ------------ arg0         \--*  LCL_VAR   long   V05 tmp4         

The extra code after the return is necessary to make JIT introduce locals and assignments for the inlining. When emitting code, we end up not emitting the zero extension:

Generating: N117 (???,???) [000121] ------------                 IL_OFFSET void   IL offset: 0x15 REG NA
Generating: N119 (  1,  1) [000040] ------------        t40 =    LCL_VAR   int    V04 tmp3         u:2 rcx (last use) REG rcx <l:$392, c:$391>
                                                              /--*  t40    int    
Generating: N121 (  2,  3) [000041] ------------        t41 = *  CAST      long <- int REG rcx <l:$243, c:$242>
							V04 in reg rcx is becoming dead  [000040]
							Live regs: 00000002 {rcx} => 00000000 {}
							Live vars: {V04} => {}
IN0017:        movsxd   rcx, ecx
                                                              /--*  t41    long   
Generating: N123 (  6,  6) [000043] DA----------              *  STORE_LCL_VAR long   V03 tmp2         d:2 rcx REG rcx
							V03 in reg rcx is becoming live  [000043]
							Live regs: 00000000 {} => 00000002 {rcx}
							Live vars: {} => {V03}
Generating: N125 (  3,  2) [000044] C-----------        t44 =    LCL_VAR   int    V03 tmp2         u:2 rcx (last use) REG rcx <l:$396, c:$395>
                                                              /--*  t44    int    
Generating: N127 (  4,  4) [000037] ---------U--        t37 = *  CAST      long <- ulong <- uint REG rcx <l:$245, c:$244>
							V03 in reg rcx is becoming dead  [000044]
							Live regs: 00000002 {rcx} => 00000000 {}
							Live vars: {V03} => {}
                                                              /--*  t37    long   
Generating: N129 (  4,  4) [000051] DA----------              *  STORE_LCL_VAR long   V05 tmp4         d:2 rcx REG rcx
							V05 in reg rcx is becoming live  [000051]
							Live regs: 00000000 {} => 00000002 {rcx}
							Live vars: {} => {V05}
Generating: N131 (  1,  1) [000048] ------------        t48 =    LCL_VAR   long   V05 tmp4         u:2 rcx (last use) REG rcx <l:$245, c:$244>
                                                              /--*  t48    long   
Generating: N133 (???,???) [000134] ------------       t134 = *  PUTARG_REG long   REG rcx
							V05 in reg rcx is becoming dead  [000048]
							Live regs: 00000002 {rcx} => 00000000 {}
							Live vars: {V05} => {}
                                                              /--*  t134   long   arg0 in rcx
Generating: N135 ( 15,  7) [000049] --CXG-------              *  CALL      void   System.Console.WriteLine REG NA $VN.Void
							Call: GCvars=0000000000000000 {}, gcrefRegs=00000000 {}, byrefRegs=00000000 {}
IN0018:        call     System.Console:WriteLine(long)
@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 Jul 3, 2021
@jakobbotsch
Copy link
Member Author

jakobbotsch commented Jul 3, 2021

Looks like emitter:AreUpper32BitsZero returns true because this does not handle movsxd:

// Bail if not writing to the right register
if (id->idReg1() != reg)
{
return false;
}
// Bail if movsx, we always have movsx sign extend to 8 bytes
if (id->idIns() == INS_movsx)
{
return false;
}
// movzx always zeroes the upper 32 bits.
if (id->idIns() == INS_movzx)
{
return true;
}
// Else rely on operation size.
return (id->idOpSize() == EA_4BYTE);

I'll work on a fix.

@jakobbotsch jakobbotsch removed the untriaged New issue has not been triaged by the area owner label Jul 3, 2021
@jakobbotsch jakobbotsch self-assigned this Jul 3, 2021
@jakobbotsch jakobbotsch added this to the 6.0.0 milestone Jul 3, 2021
@ghost ghost added the in-pr There is an active PR which will close this issue when it is merged label Jul 3, 2021
@jakobbotsch
Copy link
Member Author

Another variant:

// Generated by Fuzzlyn v1.2 on 2021-07-04 17:28:16
// Seed: 1706872746311375714
// Reduced from 140.7 KiB to 1.7 KiB in 00:02:13
// Debug: Prints 1 line(s)
// Release: Prints 0 line(s)
struct S0
{
    public long F5;
    public S0(int f0, byte f1, ulong f2, byte f3, uint f4, long f5, int f6, int f7) : this()
    {
    }
}

class C0
{
    public long F0;
}

class C1
{
    public ulong F1;
}

public class Program
{
    static int[] s_2 = new int[] { -1 };
    static C0 s_4 = new C0();
    static S0 s_5;
    static C1[][] s_47 = new C1[][] { new C1[] { new C1() } };
    public static void Main()
    {
        s_5.F5 = s_2[0];
        C1 vr4 = s_47[0][0];
        var vr6 = vr4.F1;
        M6(vr6);
    }

    static void M6(ulong arg0)
    {
        arg0 >>= 0;
        if (-1 < (uint)(0U | M7(ref s_4.F0, new S0[][,] { new S0[,] { { new S0(-10, 1, 0, 178, 1671790506U, -2L, 1, -2147483648) } }, new S0[,] { { new S0(1330389305, 255, 1297834355652867458UL, 0, 1777203966U, 4402572156859115751L, -1597826478, 1) } }, new S0[,] { { new S0(2147483646, 15, 18446744073709551614UL, 9, 1089668776U, 8629324174561266356L, 2124906017, -1883510008) } } }, 1, new sbyte[] { -37, -21, 0, 0, 0, 0 }, new S0[] { new S0(219671235, 22, 11763641210444381762UL, 0, 2568868236U, -7432636731544997849L, 1623417447, -479936755), new S0(-2147483647, 108, 0, 1, 4294967294U, 9223372036854775807L, 539462011, 1), new S0(1, 0, 15733997012901423027UL, 212, 4294967294U, 4663434921694141184L, -2147483647, 1196938120), new S0(1, 68, 0, 14, 653907833U, -6962955672558660864L, 1966270988, -378944819) })))
        {
            bool[] vr17 = new bool[] { true };
            System.Console.WriteLine(vr17[0]);
        }
    }

    static short M7(ref long arg0, S0[][,] arg1, ushort arg2, sbyte[] arg3, S0[] arg4)
    {
        long vr20 = s_5.F5;
        return (short)vr20;
    }
}

jakobbotsch added a commit to jakobbotsch/runtime that referenced this issue Jul 9, 2021
@ghost ghost removed the in-pr There is an active PR which will close this issue when it is merged label Jul 10, 2021
@ghost ghost locked as resolved and limited conversation to collaborators Aug 9, 2021
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