Skip to content

On "llvmcall with integer pointers is deprecated, use an actual pointer type instead." on nightly #53916

@sumiya11

Description

@sumiya11

#53687 seems to have introduced this warning recently to promote the use of i8* and ptr instead of i64 for pointers in llvmcall .

Curiously, the use of i8* over i64 seems to have an impact on the actual generated code (on 1.10.2). Consider the two functions:
 

@generated function foo_old(a::Vector{UInt32})  # same as `@inbounds a[1]`
    textir = """
    define i32 @entry(i64 %0) #0 {
        %arr = inttoptr i64 %0 to i32*
        %arr.i = getelementptr inbounds i32, i32* %arr, i64 0
        %x = load i32, i32* %arr.i, align 4
        ret i32 %x
    }
    attributes #0 = { alwaysinline }
    """
    quote
        GC.@preserve a begin
            Base.llvmcall(($textir, "entry"), UInt32, Tuple{Ptr{UInt32}}, pointer(a))
        end
    end
end

@generated function foo_new(a::Vector{UInt32})
    textir = """
    define i32 @entry(i8* %0) #0 {
        %arr = bitcast i8* %0 to i32*
        %arr.i = getelementptr inbounds i32, i32* %arr, i64 0
        %x = load i32, i32* %arr.i, align 4
        ret i32 %x
    }
    attributes #0 = { alwaysinline }
    """
    quote
        GC.@preserve a begin
            Base.llvmcall(($textir, "entry"), UInt32, Tuple{Ptr{UInt32}}, pointer(a))
        end
    end
end

The IR of foo_new reported by @code_llvm has an additional call:

@code_llvm debuginfo = :none foo_old([UInt32(1)])
; Function Attrs: uwtable
define i32 @julia_foo_old_2191({}* noundef nonnull align 16 dereferenceable(40) %0) #0 {
top:
  %1 = bitcast {}* %0 to i32**
  %arrayptr2 = load i32*, i32** %1, align 8
  %x.i = load i32, i32* %arrayptr2, align 4
  ret i32 %x.i
}

@code_llvm debuginfo = :none foo_new([UInt32(1)])
; Function Attrs: uwtable
define i32 @julia_foo_new_2194({}* noundef nonnull align 16 dereferenceable(40) %0) #0 {
top:
  %1 = bitcast {}* %0 to i8**
  %arrayptr2 = load i8*, i8** %1, align 8
  %2 = call i32 @julia_foo_new_2194u2196(i8* nonnull %arrayptr2)
  ret i32 %2
}

The assembly reported by @code_native differs as well.
The extra nanosecond here "confirms" that there is some difference:

@btime foo_old($([UInt32(9)]));
  2.600 ns (0 allocations: 0 bytes)

@btime foo_new($([UInt32(9)]));
  3.800 ns (0 allocations: 0 bytes)

I wonder if this is expected ?

On master e9d25ca , foo_old and foo_new are identical.

julia> versioninfo()
Julia Version 1.10.2
Commit bd47eca2c8 (2024-03-01 10:14 UTC)
Build Info:
  Official https://julialang.org/ release
Platform Info:
  OS: Windows (x86_64-w64-mingw32)
  CPU: 8 × Intel(R) Core(TM) i5-8250U CPU @ 1.60GHz
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-15.0.7 (ORCJIT, skylake)
Threads: 1 default, 0 interactive, 1 GC (on 8 virtual cores)
Environment:
  JULIA_EDITOR = code
  JULIA_NUM_THREADS = 4

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions