Keno / SIUnits.jl

Efficient unit-checked computation
Other
70 stars 26 forks source link

Composite type + not inlining with SIUnits #16

Open willowless opened 10 years ago

willowless commented 10 years ago

The SIUnits is great because it ends up doing a no-op when the type of the quantity is the same. However, when you're using a composite type to represent a vector, such as with ImmutableArrays (or other code similar to it), for some reason the SIQuantity.+ method does not inline, despite all type information being resolved:

using ImmutableArrays
using SIUnits
using SIUnits.ShortUnits

# Let's make sure the SIQuantity.+ is compiled, paranoia.
10m + 20m

code_llvm(+, (Vector2{typeof(0m)}, Vector2{typeof(0m)}))

define %Vector2 @"julia_+1063"(%Vector2, %Vector2) {
top:
  %2 = extractvalue %Vector2 %0, 0, !dbg !5399, !julia_type !5404
  %3 = extractvalue %Vector2 %1, 0, !dbg !5399, !julia_type !5404
  %4 = call %SIQuantity.7 @"julia_+1029"(%SIQuantity.7 %2, %SIQuantity.7 %3), !dbg !5399, !julia_type !5404
  %5 = extractvalue %Vector2 %0, 1, !dbg !5399, !julia_type !5404
  %6 = extractvalue %Vector2 %1, 1, !dbg !5399, !julia_type !5404
  %7 = call %SIQuantity.7 @"julia_+1029"(%SIQuantity.7 %5, %SIQuantity.7 %6), !dbg !5399, !julia_type !5404
  %8 = call %Vector2 @julia_Vector2(%SIQuantity.7 %4, %SIQuantity.7 %7), !dbg !5399, !julia_type !5405
  ret %Vector2 %8, !dbg !5399
}

In this method you can see the SIQuantity.+ in Julia 0.2.0. Tim Holy also had a go with a newer version of Julia and replied the following to me: "With regards to your specific question, my version of Julia (a relatively recent build from master) inlines the "+" operation but still issues a pair of calls for a conversion; I agree those seem unnecessary."

The JIT is not inlining the calls either, so the native code on my x86_64 platform ends up like this: code_native(+, (Vector2{typeof(0m)}, Vector2{typeof(0m)}))

    .section    __TEXT,__text,regular,pure_instructions
Filename: /Users/michaell/.julia/v0.2/ImmutableArrays/src/generate_arrays.jl
Source line: 113
    push    RBP
    mov RBP, RSP
    push    R15
    push    R14
    push    R12
    push    RBX
    mov R14, RCX
    mov R15, RSI
Source line: 113
    movabs  R12, 4373096032
    mov RSI, RDX
    call    R12
    mov RBX, RAX
    mov RDI, R15
    mov RSI, R14
    call    R12
    movabs  RCX, 4373096288
    mov RDI, RBX
    mov RSI, RAX
    call    RCX
    pop RBX
    pop R12
    pop R14
    pop R15
    pop RBP
    ret

It's possible MCJIT will magically inline at the native code level, but I would have thought Julia would have inlined at the LLVM IR level. My assumptions about how, why and when it would inline are probably invalid though.

I hope this helps.

Keno commented 10 years ago

There is a problem with inlining of methods on Vector2, I've come across this myself. I hope to just solve that once and for all soon, by making tuples acts as n vectors so the ImmutableArrays hack shouldn't be necessary. I also have some thoughts on how to improve type inference and I will make sure that this package works as expected with no overhead in the usual cases (part of what I'll be focusing on this summer). Thank you for the issue report though. I'll be sure to test this after.