Manually adding an Expr(:meta, :inline) to the function is not equivalent 
to using @inline since it does not “splice” it into the function’s ast but 
rather just creates a new Expr object at runtime each time the function is 
called. Have a look at the difference in code_typed output between foo2 and 
the following function

@inline function foo3{T}(x::T)
    x.data[1]
end

julia> code_warntype(foo3, (Bar,))
Variables:
  #self#::#foo3
  x::Bar

Body:
  begin 
      $(Expr(:meta, :inline)) # none, line 2:
      return 
(Base.getfield)((top(getfield))(x::Bar,:data)::Tuple{Int64,Float64,Bool},1)::Int64
  end::Int64

You should always use @inline unless you’re manually building an entire Expr 
to be returned by a macro or generated function.

— Mike
​

On Thursday, 11 February 2016 08:37:17 UTC+2, Andy Ferris wrote:
>
> Hi,
>
> I have been playing with inlining and I'm confused by the following - my 
> inline function `foo2` is clearly less efficient than my normal function 
> `foo`.
>
> Does anyone have insight to what is going on? Would this have to do with 
> running everything in Main from the REPL (so that it would be OK in 
> practice)? Is the inline tag doing something else I wouldn't expect? 
> Running `code_warntype` indicates both have strongly typed outputs.
>
> Thanks,
> Andy
>
>
> julia> immutable Bar
>           data::Tuple{Int64,Float64,Bool}
>        end
>
>
> julia> function foo{T}(x::T)
>            x.data[1]
>        end
> foo (generic function with 1 method)
>
>
> julia> function foo2{T}(x::T)
>            Expr(:meta,:inline)
>            x.data[1]
>        end
> foo2 (generic function with 1 method)
>
>
> julia> code_native(foo,(Bar,))
> .text
> Filename: none
> Source line: 2
> pushq %rbp
> movq %rsp, %rbp
> Source line: 2
> movq (%rdi), %rax
> Source line: 2
> popq %rbp
> ret
>
>
> julia> code_native(foo2,(Bar,))
> .text
> Filename: none
> Source line: 2
> pushq %rbp
> movq %rsp, %rbp
> Source line: 2
> pushq %r14
> pushq %rbx
> subq $32, %rsp
> movq $4, -48(%rbp)
> movabsq $jl_pgcstack, %r14
> movq (%r14), %rax
> movq %rax, -40(%rbp)
> leaq -48(%rbp), %rax
> movq %rax, (%r14)
> xorps %xmm0, %xmm0
> movups %xmm0, -32(%rbp)
> movq (%rdi), %rbx
> movabsq $140270402987792, %rax  # imm = 0x7F933F8AE710
> Source line: 2
> movq %rax, -32(%rbp)
> Source line: 2
> leaq -32(%rbp), %rsi
> Source line: 2
> movabsq $jl_f_new_expr, %rax
> movabsq $140270402996640, %rcx  # imm = 0x7F933F8B09A0
> movq %rcx, -24(%rbp)
> xorl %edi, %edi
> movl $2, %edx
> callq *%rax
> Source line: 3
> movq -40(%rbp), %rax
> movq %rax, (%r14)
> movq %rbx, %rax
> addq $32, %rsp
> popq %rbx
> popq %r14
> popq %rbp
> ret
>
>
> Also:
>
> julia> code_llvm(foo,(bar,))
>
> define i64 @julia_foo_26276(%bar*) {
> top:
>   %1 = bitcast %bar* %0 to i64*
>   %2 = load i64* %1, align 8
>   ret i64 %2
> }
>
>
> julia> code_llvm(foo2,(bar,))
>
> define i64 @julia_foo2_26277(%bar*) {
> top:
>   %1 = alloca [4 x %jl_value_t*], align 8
>   %.sub5 = bitcast [4 x %jl_value_t*]* %1 to %jl_value_t**
>   %2 = getelementptr [4 x %jl_value_t*]* %1, i64 0, i64 2
>   store %jl_value_t* inttoptr (i64 4 to %jl_value_t*), %jl_value_t** 
> %.sub5, align 8
>   %3 = getelementptr [4 x %jl_value_t*]* %1, i64 0, i64 1
>   %4 = load %jl_value_t*** @jl_pgcstack, align 8
>   %.c = bitcast %jl_value_t** %4 to %jl_value_t*
>   store %jl_value_t* %.c, %jl_value_t** %3, align 8
>   store %jl_value_t** %.sub5, %jl_value_t*** @jl_pgcstack, align 8
>   store %jl_value_t* null, %jl_value_t** %2, align 8
>   %5 = getelementptr [4 x %jl_value_t*]* %1, i64 0, i64 3
>   store %jl_value_t* null, %jl_value_t** %5, align 8
>   %6 = bitcast %bar* %0 to i64*
>   %7 = load i64* %6, align 8
>   store %jl_value_t* inttoptr (i64 140270402987792 to %jl_value_t*), 
> %jl_value_t** %2, align 8
>   store %jl_value_t* inttoptr (i64 140270402996640 to %jl_value_t*), 
> %jl_value_t** %5, align 8
>   %8 = call %jl_value_t* @jl_f_new_expr(%jl_value_t* null, %jl_value_t** 
> %2, i32 2)
>   %9 = load %jl_value_t** %3, align 8
>   %10 = bitcast %jl_value_t* %9 to %jl_value_t**
>   store %jl_value_t** %10, %jl_value_t*** @jl_pgcstack, align 8
>   ret i64 %7
> }
>
>
> julia> code_warntype(foo,(bar,))
> Variables:
>   x::bar
>
> Body:
>   begin  # none, line 2:
>       return 
> (Base.getfield)((top(getfield))(x::bar,:data)::Tuple{Int64,Float64,Bool},1)::Int64
>   end::Int64
>
>
> julia> code_warntype(foo2,(bar,))
> Variables:
>   x::bar
>   ##args#10160::Tuple{Symbol,Symbol}
>
> Body:
>   begin  # none, line 2:
>       (Base._expr)(:meta,:inline)::Expr # none, line 3:
>       return 
> (Base.getfield)((top(getfield))(x::bar,:data)::Tuple{Int64,Float64,Bool},1)::Int64
>   end::Int64
>
>

Reply via email to