Thank you Mike for clearing that up. Actually, the docs say @inline simply inserts that :meta: http://docs.julialang.org/en/release-0.4/devdocs/meta/. Maybe that's too simplistic.
Actually, I *was* looking at this because I wanted to make inline generated functions and see how they behave with code_native/code_llvm. But as you can see from https://groups.google.com/forum/#!topic/julia-users/4pkWhcap1Zg I have been struggling to see the code from generated functions, so I did as Tim Holy suggested and stuck the code into a function and saw how it compiled (since I couldn't figure out another way). I'm assuming including the Expr(:meta,:inline) is the correct thing to do for generated functions? Andy On Thursday, February 11, 2016 at 5:46:40 PM UTC+10, Michael Hatherly wrote: > > 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 >> >>
