dotnet / runtime

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

RyuJIT zero-extends instead of sign-extending on ARM32 in debug #10639

Closed jakobbotsch closed 4 years ago

jakobbotsch commented 6 years ago

On ARM32 running .NET core 2.1.301 the following program prints FFFFFFFE in release, but FE in debug:

class C0
{
    public sbyte F3;
    public C0(sbyte f3)
    {
        F3 = f3;
    }
}

public class Program
{
    static C0 s_14 = new C0(-1);
    public static void Main()
    {
        long vr1 = s_14.F3 + (uint)s_14.F3;
        System.Console.WriteLine("{0:X}", vr1);
    }
}

The correct result is FFFFFFFE. I don't have access to the dump/disasm as I still haven't managed to get coreclr to build on ARM32, but my guess is that the right operand is zero-extended instead of sign-extended. The result is the same as if the uint cast was replaced by a byte cast. This one does not reproduce on x86 or x64 using either .NET core 2.1 or current head.

mikedn commented 6 years ago

I don't have access to the dump/disasm as I still haven't managed to get coreclr to build on ARM32

You can use the AltJit feature on a x86 checked build to get the ARM32 disassembly

COMPLUS_JitDisasm=Main
COMPLUS_AltJit=Main
COMPLUS_AltJitName=protononjit.dll
corerun test.exe
jakobbotsch commented 6 years ago

Thanks, that's very useful!

It looks right with AltJit:

; Assembly listing for method Program:M1()
; Emitting BLENDED_CODE for generic ARM CPU
; debuggable code
; r11 based frame
; fully interruptible
; Final local variable assignments
;
;  V00 loc0         [V00,T01] (  3,  3   )    long  ->  [sp+0x08]   do-not-enreg[] must-init
;# V01 OutArgs      [V01    ] (  1,  1   )  lclBlk ( 0) [sp+0x00]   do-not-enreg[]
;  V02 tmp1         [V02,T00] (  3,  6   )     int  ->  [sp+0x04]   do-not-enreg[] must-init
;
; Lcl frame size = 16

G_M63615_IG01:
000000  E92D 4C10      push    {r4,r10,r11,lr}
000004  B084           sub     sp, 16
000006  F10D 0B18      add     r11, sp, 24
00000A  2000           movs    r0, 0
00000C  9002           str     r0, [sp+0x08]    // [V00 loc0]
00000E  9003           str     r0, [sp+0x0c]    // [V00 loc0+0x04]
000010  9001           str     r0, [sp+0x04]    // [V02 tmp1]

G_M63615_IG02:
000012  F643 73D8      movw    r3, 0x3fd8
000016  F2C0 23F0      movt    r3, 0x2f0
00001A  681B           ldr     r3, [r3]
00001C  2B00           cmp     r3, 0
00001E  D004           beq     SHORT G_M63615_IG03
000020  F24D 1330      movw    r3, 0xd130
000024  F6C0 7378      movt    r3, 0xf78
000028  4798           blx     r3               // CORINFO_HELP_DBG_IS_JUST_MY_CODE

G_M63615_IG03:
00002A  BF00           nop
00002C  F641 40B0      movw    r0, 0x1cb0
000030  F2C0 602D      movt    r0, 0x62d
000034  6800           ldr     r0, [r0]                            |
000036  F990 0004      ldrsb   r0, [r0+4]                          |
00003A  9001           str     r0, [sp+0x04]    // [V02 tmp1]      |
00003C  9801           ldr     r0, [sp+0x04]    // [V02 tmp1]      |
00003E  9901           ldr     r1, [sp+0x04]    // [V02 tmp1]      |
000040  17C9           asrs    r1, r1, 31                          | r1:r0 = (long)s_14.F3
000042  F641 43B0      movw    r3, 0x1cb0
000046  F2C0 632D      movt    r3, 0x62d
00004A  681B           ldr     r3, [r3]                            |
00004C  F993 3004      ldrsb   r3, [r3+4]                          |
000050  B25B           sxtb    r3, r3                              | r3 = (int)s_14.F3
000052  2200           movs    r2, 0
000054  18C0           adds    r0, r0, r3                          | r0 += r3, save carry
000056  4151           adcs    r1, r2                              | r1 += carry
000058  9002           str     r0, [sp+0x08]    // [V00 loc0]
00005A  9103           str     r1, [sp+0x0c]    // [V00 loc0+0x04]
00005C  9802           ldr     r0, [sp+0x08]    // [V00 loc0]
00005E  9903           ldr     r1, [sp+0x0c]    // [V00 loc0+0x04]
000060  F645 53EC      movw    r3, 0x5dec
000064  F2C0 23F0      movt    r3, 0x2f0
000068  681B           ldr     r3, [r3]
00006A  4798           blx     r3               // System.Console:WriteLine(long)
00006C  BF00           nop
00006E  BF00           nop

G_M63615_IG04:
000070  B004           add     sp, 16
000072  E8BD 8C10      pop     {r4,r10,r11,pc}

; Total bytes of code 118, prolog size 18 for method Program:M1()
; ============================================================

I tracked down the actual code generated on my ARM32 box. It has generated uxtb instead:

   0xb45254f8:  stmdb   sp!, {r4, r10, r11, lr}
   0xb45254fc:  sub     sp, dotnet/coreclr#16
   0xb45254fe:  add.w   r11, sp, dotnet/coreclr#24
   0xb4525502:  movs    r0, #0
   0xb4525504:  str     r0, [sp, dotnet/coreclr#8]
   0xb4525506:  str     r0, [sp, dotnet/coreclr#12]
   0xb4525508:  str     r0, [sp, dotnet/coreclr#4]
   0xb452550a:  str     r0, [sp, #0]
   0xb452550c:  movw    r3, #48812      ; 0xbeac
   0xb4525510:  movt    r3, #46299      ; 0xb4db
   0xb4525514:  ldr     r3, [r3, #0]
   0xb4525516:  cmp     r3, #0
   0xb4525518:  beq.n   0xb4525524
   0xb452551a:  movw    r3, #39477      ; 0x9a35
   0xb452551e:  movt    r3, #46720      ; 0xb680
   0xb4525522:  blx     r3
   0xb4525524:  nop
   0xb4525526:  movw    r0, dotnet/runtime#5120       ; 0xc60
   0xb452552a:  movt    r0, #45728      ; 0xb2a0
   0xb452552e:  ldr     r0, [r0, #0]
   0xb4525530:  ldrsb.w r0, [r0, dotnet/coreclr#4]
   0xb4525534:  str     r0, [sp, #0]
   0xb4525536:  ldr     r0, [sp, #0]
   0xb4525538:  ldr     r1, [sp, #0]
   0xb452553a:  asrs    r1, r1, dotnet/runtime#3863
   0xb452553c:  movw    r3, dotnet/runtime#5120       ; 0xc60
   0xb4525540:  movt    r3, #45728      ; 0xb2a0
   0xb4525544:  ldr     r3, [r3, #0]
   0xb4525546:  ldrsb.w r3, [r3, dotnet/coreclr#4]
   0xb452554a:  uxtb    r3, r3             <- zero extend instead of sign extend
   0xb452554c:  movs    r2, #0
   0xb452554e:  adds    r0, r0, r3
   0xb4525550:  adcs    r1, r2
   0xb4525552:  str     r0, [sp, dotnet/coreclr#8]
   0xb4525554:  str     r1, [sp, dotnet/coreclr#12]
   0xb4525556:  ldr     r0, [sp, dotnet/coreclr#8]
   0xb4525558:  ldr     r1, [sp, dotnet/coreclr#12]
   0xb452555a:  movw    r3, #55136      ; 0xd760
   0xb452555e:  movt    r3, #46299      ; 0xb4db
   0xb4525562:  ldr     r3, [r3, #0]

After looking around a bit I see that this is probably a duplicate of dotnet/runtime#10345 which is already fixed in master.

mikedn commented 6 years ago

After looking around a bit I see that this is probably a duplicate of dotnet/runtime#10345 which is already fixed in master.

Yep, that looks like it.