A Case for a Native Runtime Compilation Language
jott.live
jott.live
function foo(a, xs)
function bar(b)
b * a
end
res = 0
for x in xs
res += bar(x)
end
res
end
what the author desires (the lifting of a to a compile time constant) won't happen automatically because compiling a new bar for every value of a is going to be a bad idea unless the loop over xs takes longer than compiling a function. Hence, we make people 'opt-in' to this by lifting a from a runtime variable to a type parameter (julia types are parametric and their parameters can contain values).Hence, one way to do this would be to write
foo(a, xs) = foo(Val{a}, xs)
function foo(::Type{Val{a}}, xs) where {a}
function bar(b)
b * a
end
res = 0
for x in xs
res += bar(x)
end
res
end
Now, when you run foo(2, v) (where v is some iterable), this will turn into foo(Val{2}, v) which then gets specialized on the type parameter {2}, and then can compile a new bar function that's aware of the value of a.Here's an example at the repl where we can inspect the generated code more easily:
julia> f(a) = f(Val{a})
f (generic function with 1 method)
julia> function f(::Type{Val{a}}) where {a}
function g(b)
b * a
end
end
f (generic function with 2 methods)
julia> g1 = f(1)
(::var"#g#4"{1}) (generic function with 1 method)
julia> @code_llvm debuginfo=:none g1(4)
define i64 @julia_g_442(i64 signext %0) {
top:
ret i64 %0
}
julia> g2 = f(2)
(::var"#g#4"{2}) (generic function with 1 method)
julia> @code_llvm debuginfo=:none g2(4)
define i64 @julia_g_444(i64 signext %0) {
top:
%1 = shl i64 %0, 1
ret i64 %1
}
Notice that g1 and g2 have different optimizations applied that depend on the different runtime values of a. a = 2
function f(n)
return n * a
end
println(f(4))
@code_llvm f(4)
@code_native f(4) const a = 2
f(n) = n * a
julia> @code_llvm f(4)
; @ REPL[2]:1 within `f'
define i64 @julia_f_290(i64 signext %0) {
top:
; @ REPL[2]:2 within `f'
; ┌ @ int.jl:88 within `*'
%1 = shl i64 %0, 1
; └
ret i64 %1
}
julia> @code_native f(4)
.text
; ┌ @ REPL[2]:2 within `f'
; │┌ @ int.jl:88 within `*'
leaq (%rdi,%rdi), %rax
; │└
retq
nopw %cs:(%rax,%rax)
; └