Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

varargs generated functions generate inefficient code #12643

Closed
mlubin opened this issue Aug 16, 2015 · 4 comments
Closed

varargs generated functions generate inefficient code #12643

mlubin opened this issue Aug 16, 2015 · 4 comments

Comments

@mlubin
Copy link
Member

mlubin commented Aug 16, 2015

The following was unexpected:

@generated function bar(args...)
    :( args[1] )
end

julia> @code_llvm bar(1,2,3)

define %jl_value_t* @julia_bar_21185(%jl_value_t*, %jl_value_t**, i32) {
top:
  %3 = alloca [3 x %jl_value_t*], align 8
  %.sub = getelementptr inbounds [3 x %jl_value_t*]* %3, i64 0, i64 0
  %4 = getelementptr [3 x %jl_value_t*]* %3, i64 0, i64 2
  store %jl_value_t* inttoptr (i64 2 to %jl_value_t*), %jl_value_t** %.sub, align 8
  %5 = getelementptr [3 x %jl_value_t*]* %3, i64 0, i64 1
  %6 = load %jl_value_t*** @jl_pgcstack, align 8
  %.c = bitcast %jl_value_t** %6 to %jl_value_t*
  store %jl_value_t* %.c, %jl_value_t** %5, align 8
  store %jl_value_t** %.sub, %jl_value_t*** @jl_pgcstack, align 8
  store %jl_value_t* null, %jl_value_t** %4, align 8
  %7 = icmp eq i32 %2, 0
  br i1 %7, label %fail, label %pass

fail:                                             ; preds = %top
  call void @jl_bounds_error_tuple_int(%jl_value_t** %1, i64 0, i64 1)
  unreachable

pass:                                             ; preds = %top
  %8 = load %jl_value_t** %1, align 8
  %9 = load %jl_value_t** %5, align 8
  %10 = getelementptr inbounds %jl_value_t* %9, i64 0, i32 0
  store %jl_value_t** %10, %jl_value_t*** @jl_pgcstack, align 8
  ret %jl_value_t* %8
}

I was hoping that the code would look more like this:

function bar2(a,b,c)
    return a
end

julia> @code_llvm bar2(1,2,3)

define i64 @julia_bar2_21186(i64, i64, i64) {
top:
  ret i64 %0
}

Am I doing anything wrong?

CC @joehuchette

@yuyichao
Copy link
Contributor

I think this is the issue we have for varargs functions in general. Not just generated functions. The code is pretty terrible when we generate a jlcall signature.

One workaround is that if the function can be inlined, it might not suffer from this issue.

Close as a duplicate of #11248 (or possibly other issues linked there)

@yuyichao
Copy link
Contributor

See also #5402

@mlubin
Copy link
Member Author

mlubin commented Aug 16, 2015

Naive question, but why does a varargs generated function have to generate a varargs method? The number of arguments is known at generation time.

@yuyichao
Copy link
Contributor

I don't think the current implementation have any special handling for that. The signature of the generated function is the same with the signature of the original function.

In some sense, this is exactly the same issue I described in #11248. For f(args...) the type of args is also known at compile time and the compiler should be able to generate code as effecient as f(args) (called with a tuple). Especially after #10380

Another way to workaround this is probably to define (either generated or not) @inline f(args...) = _f(args) and _f(args) = ...

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants