JuliaLang / julia

The Julia Programming Language
https://julialang.org/
MIT License
45.72k stars 5.48k forks source link

`@code_native` is often unreadable #53979

Open LilithHafner opened 7 months ago

LilithHafner commented 7 months ago

I recently wanted to see the assembly of rand(UInt), and found this result somewhat disappointing:

julia> @code_native rand(UInt)
        .text
        .file   "rand"
        .globl  julia_rand_5155                 // -- Begin function julia_rand_5155
        .p2align        2
        .type   julia_rand_5155,@function
julia_rand_5155:                        // @julia_rand_5155
; Function Signature: rand(Type{UInt64})
; ┌ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand`
// %bb.0:                               // %top
        stp     x29, x30, [sp, #-16]!           // 16-byte Folded Spill
        mov     x29, sp
        //APP
        mrs     x8, TPIDR_EL0
        //NO_APP
        ldr     x8, [x8, #16]
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:261
; │┌ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:224 within `getstate`
; ││┌ @ task.jl:186 within `getproperty`
        ldp     x9, x10, [x8, #-56]
        ldp     x11, x12, [x8, #-40]
; │└└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:262
; │┌ @ int.jl:87 within `+`
        add     x13, x12, x9
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:263
; │┌ @ int.jl:372 within `|`
        ror     x13, x13, #41
; │└
; │┌ @ int.jl:87 within `+`
        add     x0, x13, x9
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:265
; │┌ @ int.jl:373 within `xor`
        eor     x11, x11, x9
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:266
; │┌ @ int.jl:373 within `xor`
        eor     x12, x12, x10
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:267
; │┌ @ int.jl:373 within `xor`
        eor     x13, x11, x10
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:268
; │┌ @ int.jl:373 within `xor`
        eor     x9, x12, x9
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:270
; │┌ @ int.jl:372 within `|`
        ror     x12, x12, #19
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:269
; │┌ @ int.jl:373 within `xor`
        eor     x10, x11, x10, lsl #17
; │└
; │ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand` @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:256 @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:271
; │┌ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:212 within `setstate!`
; ││┌ @ task.jl:194 within `setproperty!` @ Base.jl:53
        stp     x9, x13, [x8, #-56]
; ││└
; ││ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:214 within `setstate!`
; ││┌ @ task.jl:194 within `setproperty!` @ Base.jl:53
        stp     x10, x12, [x8, #-40]
; ││└
; ││ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Xoshiro.jl:215 within `setstate!`
; ││┌ @ task.jl:194 within `setproperty!` @ Base.jl:53
        ldp     x29, x30, [sp], #16             // 16-byte Folded Reload
        ret
.Lfunc_end0:
        .size   julia_rand_5155, .Lfunc_end0-julia_rand_5155
; └└└
                                        // -- End function
        .section        ".note.GNU-stack","",@progbits

It's even worse with line wrapping enabled.

1.6 was more ineligible, though it's much longer because MerseneTwister took more instructions than the current RNG.

julia> @code_native rand(UInt)
        .text
; ┌ @ Random.jl:259 within `rand'
        sub     sp, sp, #64                     // =64
        str     x30, [sp, #32]
        stp     x20, x19, [sp, #48]
        mov     w8, #4
        stp     xzr, xzr, [sp]
        str     xzr, [sp, #16]
; │┌ @ RNGs.jl:370 within `default_rng'
; ││┌ @ threadingconstructs.jl:10 within `threadid'
        str     x8, [sp]
        mrs     x20, TPIDR_EL0
        ldr     x8, [x20, #16]
        mov     x9, sp
        str     x8, [sp, #8]
        ldrsh   x8, [x20, #32]
        str     x9, [x20, #16]
; │││┌ @ int.jl:923 within `+' @ int.jl:87
        add     x0, x8, #1                      // =1
; ││└└
        bl      0x9c
; │└
; │ @ Random.jl:259 within `rand' @ Random.jl:256 @ RNGs.jl:464
; │┌ @ RNGs.jl:296 within `mt_pop!'
; ││┌ @ RNGs.jl:291 within `reserve1'
; │││┌ @ Base.jl:33 within `getproperty'
        ldr     x8, [x0, #40]
; │└└└
; │ @ Random.jl:259 within `rand'
; │┌ @ RNGs.jl:370 within `default_rng'
        mov     x19, x0
; │└
; │ @ Random.jl:259 within `rand' @ Random.jl:256 @ RNGs.jl:464
; │┌ @ RNGs.jl:296 within `mt_pop!'
; ││┌ @ RNGs.jl:291 within `reserve1'
        cmp     x8, #7                          // =7
        b.gt    L92
        mov     x0, x19
        str     x19, [sp, #16]
        bl      0x94
; │└└
; │┌ @ RNGs.jl:297 within `mt_pop!'
; ││┌ @ Base.jl:33 within `getproperty'
        ldr     x8, [x19, #40]
; │└└
; │┌ @ RNGs.jl:299 within `mt_pop!'
; ││┌ @ Base.jl:33 within `getproperty'
L92:
        ldr     x9, [x19, #24]
; │└└
; │┌ @ RNGs.jl:297 within `mt_pop!'
; ││┌ @ int.jl:86 within `-'
        sub     x8, x8, #8                      // =8
; ││└
; ││┌ @ Base.jl:34 within `setproperty!'
        str     x8, [x19, #40]
; │└└
; │┌ @ RNGs.jl:299 within `mt_pop!'
; ││┌ @ int.jl:462 within `>>' @ int.jl:455
        and     x10, x8, #0xfffffffffffffff0
; ││└
; ││┌ @ array.jl:805 within `getindex'
        ldr     x9, [x9]
; │└└
; │┌ @ RNGs.jl:301 within `mt_pop!'
; ││┌ @ int.jl:88 within `*'
        lsl     w8, w8, #3
        and     x11, x8, #0x40
; ││└
; ││┌ @ int.jl:462 within `>>' @ int.jl:456
        ands    x8, x8, #0x40
; │└└
; │┌ @ RNGs.jl:299 within `mt_pop!'
; ││┌ @ array.jl:805 within `getindex'
        add     x9, x9, x10
        ldp     x10, x9, [x9]
; │└└
; │┌ @ RNGs.jl:301 within `mt_pop!'
; ││┌ @ int.jl:462 within `>>' @ int.jl:456
        neg     x8, x8
; │└└
; │ @ Random.jl:259 within `rand'
        ldr     x30, [sp, #32]
; │ @ Random.jl:259 within `rand' @ Random.jl:256 @ RNGs.jl:464
; │┌ @ RNGs.jl:301 within `mt_pop!'
; ││┌ @ int.jl:462 within `>>' @ int.jl:456
        lsl     x8, x9, x8
        lsr     x10, x10, x11
        csel    x8, xzr, x8, eq
        orr     x8, x10, x8
        ldr     x10, [sp, #8]
        lsr     x9, x9, x11
        sub     x11, x11, #64                   // =64
        cmp     x11, #0                         // =0
        str     x10, [x20, #16]
; │└└
; │ @ Random.jl:259 within `rand'
        ldp     x20, x19, [sp, #48]
; │ @ Random.jl:259 within `rand' @ Random.jl:256 @ RNGs.jl:464
; │┌ @ RNGs.jl:301 within `mt_pop!'
; ││┌ @ int.jl:462 within `>>' @ int.jl:456
        csel    x0, x9, x8, ge
; │└└
; │ @ Random.jl:259 within `rand'
        add     sp, sp, #64                     // =64
        ret
; └
maleadt commented 7 months ago

That's https://github.com/JuliaLang/julia/pull/41789; you can still access the old disassembling version by (rather crypticly) specifying dump_module=false:

julia> @code_native dump_module=false rand(UInt)
    .text
; ┌ @ Random.jl:261 within `rand`
    push    rbp
    mov rbp, rsp
    mov rax, qword ptr [r13 + 16]
    mov rax, qword ptr [rax + 16]
    mov rax, qword ptr [rax]
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:143
; │┌ @ task.jl:182 within `getproperty`
    mov rcx, qword ptr [r13 - 56]
    mov rsi, qword ptr [r13 - 32]
    mov rdi, qword ptr [r13 - 40]
    mov rdx, qword ptr [r13 - 48]
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:144
; │┌ @ int.jl:87 within `+`
    lea rax, [rsi + rcx]
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:146
; │┌ @ int.jl:536 within `<<` @ int.jl:529
    mov r8, rdx
    shl r8, 17
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:147
; │┌ @ int.jl:373 within `xor`
    xor rdi, rcx
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:148
; │┌ @ int.jl:373 within `xor`
    xor rsi, rdx
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:145
; │┌ @ int.jl:372 within `|`
    rorx    rax, rax, 41
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:149
; │┌ @ int.jl:373 within `xor`
    xor rdx, rdi
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:151
; │┌ @ int.jl:373 within `xor`
    xor rdi, r8
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:145
; │┌ @ int.jl:87 within `+`
    add rax, rcx
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:150
; │┌ @ int.jl:373 within `xor`
    xor rcx, rsi
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:152
; │┌ @ int.jl:372 within `|`
    rorx    rsi, rsi, 19
; │└
; │ @ Random.jl:261 within `rand` @ Random.jl:258 @ Xoshiro.jl:153
; │┌ @ Base.jl:41 within `setproperty!`
    mov qword ptr [r13 - 56], rcx
    mov qword ptr [r13 - 48], rdx
    mov qword ptr [r13 - 40], rdi
    mov qword ptr [r13 - 32], rsi
; │└
; │ @ Random.jl:261 within `rand`
    pop rbp
    ret
; └
; ┌ @ Random.jl:261 within `<invalid>`
    nop word ptr [rax + rax]
; └

cc @vtjnash

vtjnash commented 7 months ago

I don't know why is printing those long full paths there, though in general if you see a discrepancy with dump_module, it is because dump_module=false is wrong, as that does significantly more unreliable transforms on the information before printing.

maleadt commented 7 months ago

In addition to the long paths, some of the function prologue/epilogue could probably be omitted:

        .text
        .file   "rand"
        .globl  julia_rand_5155                 // -- Begin function julia_rand_5155
        .p2align        2
        .type   julia_rand_5155,@function
julia_rand_5155:                        // @julia_rand_5155
; Function Signature: rand(Type{UInt64})
; ┌ @ /cache/build/builder-armageddon-4/julialang/julia-release-1-dot-11/usr/share/julia/stdlib/v1.11/Random/src/Random.jl:259 within `rand`
// %bb.0:                               // %top
        stp     x29, x30, [sp, #-16]!           // 16-byte Folded Spill
        mov     x29, sp
        //APP
        mrs     x8, TPIDR_EL0
        //NO_APP

...

.Lfunc_end0:
        .size   julia_rand_5155, .Lfunc_end0-julia_rand_5155
; └└└
                                        // -- End function
        .section        ".note.GNU-stack","",@progbits
mikmoore commented 6 months ago

Related #52173.