Using LLVM intrinsic functions inside `llvmcall`

I’m playing around with llvmcall. I can use LLVM IR instructions (like add), but I cannot get intrinsic functions (like @llvm.abs.i32) to work. From the post Debugging float SIMD Intrinsics via llvmcall I get the impression that it should possible. However, when I try to run the example discussed in that post, I get the error “Module IR does not contain specified entry function”. (Have the arguments to llvmcall possibly changed since then?) Anyway, an example of calling an intrinsic function would be appreciated.

Did you declare the intrinsic before calling it? Like in the example?

I think so. Following the advice about the input argument type, I wrote:

using SIMD
function rsqrt(f)
    Base.llvmcall(("declare <4 x float> @llvm.x86.sse.rsqrt.ps(<4 x float>) nounwind readnone", " 
              %2 = call <4 x float> @llvm.x86.sse.rsqrt.ps(<4 x float> %0)
              ret <4 x float> %2"), Vec{4, Float32}, Tuple{NTuple{4, VecElement{Float32}},},
        (VecElement(f[1]),VecElement(f[2]),VecElement(f[3]),VecElement(f[4])))
end

Then I get

julia> rsqrt(Vec(Float32(1),Float32(1),Float32(1),Float32(1)))
ERROR: Module IR does not contain specified entry function

The documentation of llvmcall says that if the first argument is a tuple, then its second member must be “a string representing the name of the entry-point function to call”. In the example, this doesn’t seem to be the case.

I see the issue here, you are passing the IR via a tuple, that method requires a tuple with an LLVM IR module with defined functions and what function to call. The way you are using it, all the IR should be in the same string without a tuple.

Could you post a working example? I’ve already tried

@generated function f(x::Int64)
    quote
        Base.llvmcall(("""
    declare i64 @llvm.abs.i64(i64, i1)
    %x = call i64 @llvm.abs.64(i64 %0, i1 0)
    ret i64 %x
            """), Int64, Tuple{Int64}, x)
    end
end

but that gives

julia> f(1)
ERROR: Failed to parse LLVM assembly: 
<string>:3:1: error: expected instruction opcode
declare i64 @llvm.abs.i64(i64, i1)
^

I’m sorry, in your case I think you have to use the module level IR.
with declarations and a function definition

function foo(x)
       Base.llvmcall(("""
                  declare i64 @llvm.abs.i64(i64, i1)
                  define i64 @entry(i64) {
                  %x = call i64 @llvm.abs.i64(i64 %0, i1 0)
                  ret i64 %x
                  }
                      ""","entry"), Int64, Tuple{Int64}, x)
                          end

There are a bunch of examples in julia/llvmcall.jl at master · JuliaLang/julia · GitHub and
julia/llvmcall2.jl at master · JuliaLang/julia · GitHub

Great! Thanks!

1 Like