上記のJuliaでディスアセンブルをしたときはIntelチップだったので、M1(ARMチップ)でやったらどうなるかを試してみました。
julia> versioninfo() Julia Version 1.7.2 Commit bf53498635 (2022-02-06 15:21 UTC) Platform Info: OS: macOS (arm64-apple-darwin21.2.0) CPU: Apple M1 Max WORD_SIZE: 64 LIBM: libopenlibm LLVM: libLLVM-12.0.1 (ORCJIT, cyclone)
同じコードを使います。
julia> function add1(x) return x+1 end add1 (generic function with 1 method)
@code_llvm
の出力は以下のようになり、Intelチップを使ったときとほぼ同じです。
julia> @code_llvm add1(10) ; @ REPL[1]:1 within `add1` define i64 @julia_add1_124(i64 signext %0) #0 { top: ; @ REPL[1]:2 within `add1` ; ┌ @ int.jl:87 within `+` %1 = add i64 %0, 1 ; └ ret i64 %1 }
@code_native
の結果はこんな感じ。
julia> @code_native add1(10) .section __TEXT,__text,regular,pure_instructions ; ┌ @ REPL[1]:2 within `add1` ; │┌ @ int.jl:87 within `+` add x0, x0, #1 ; =1 ; │└ ret ; └
同じコードをIntelチップ用のJuliaでディスアセンブルすると以下のようになりました(Rosettaを使ってM1 Macで実行しています)。
julia> @code_native add1(10) .section __TEXT,__text,regular,pure_instructions ; ┌ @ REPL[2]:2 within `add1` ; │┌ @ int.jl:87 within `+` leaq 1(%rdi), %rax ; │└ retq nopw %cs:(%rax,%rax) nop ; └
Intel用として生成されるコードがJulia 1.0のときからも変化しているのがわかりますが、ARMとIntel用とでもだいぶ違います。建て増しを続けてきたIntelチップの命令セットに比べて、ARMのほうがシンプルに見えますね。
2022-05-08追記
Windowsマシンでもやってみました。Mac用のIntelコードと若干違うけど、誤差の範囲?
julia> versioninfo() Julia Version 1.7.2 Commit bf53498635 (2022-02-06 15:21 UTC) Platform Info: OS: Windows (x86_64-w64-mingw32) CPU: Intel(R) Core(TM) i5-10400 CPU @ 2.90GHz WORD_SIZE: 64 LIBM: libopenlibm LLVM: libLLVM-12.0.1 (ORCJIT, skylake) julia> function add1(x) return x+1 end add1 (generic function with 1 method) julia> @code_llvm add1(10) ; @ REPL[3]:1 within `add1` ; Function Attrs: uwtable define i64 @julia_add1_202(i64 signext %0) #0 { top: ; @ REPL[3]:2 within `add1` ; ┌ @ int.jl:87 within `+` %1 = add i64 %0, 1 ; └ ret i64 %1 } julia> @code_native add1(10) .text ; ┌ @ REPL[3]:1 within `add1` pushq %rbp movq %rsp, %rbp ; │ @ REPL[3]:2 within `add1` ; │┌ @ int.jl:87 within `+` leaq 1(%rcx), %rax ; │└ popq %rbp retq nopw (%rax,%rax) ; └