Skip to content

Type instability when using PtrArray with Julia v1.10 and --check-bounds=no #78

@sloede

Description

@sloede

With Julia v1.10-beta2 and --check-bounds=no, indexing into a PtrArray seems to be type unstable. When running the following MWE (mwe.jl),

using Pkg
Pkg.activate(; temp=true, io=devnull)
Pkg.add(name="StrideArrays", version="0.1.26", io=devnull)

using StrideArrays, InteractiveUtils

a = [1, 2, 3]
p = PtrArray(a)

@code_warntype p[1]

with julia-1.10 --check-bounds=no mwe.jl, we get the following output:

MethodInstance for getindex(::PtrArray{Int64, 1, (1,), Tuple{Int64}, Tuple{Nothing}, Tuple{StaticInt{1}}}, ::Int64)
  from getindex(A::PtrArray{T, 1}, i::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, StaticInt}) where T @ StrideArraysCore ~/.julia/packages/StrideArraysCore/COJRJ/src/ptr_array.jl:957
Static Parameters
  T = Int64
Arguments
  #self#::Core.Const(getindex)
  A::PtrArray{Int64, 1, (1,), Tuple{Int64}, Tuple{Nothing}, Tuple{StaticInt{1}}}
  i::Int64
Body::Any
1nothing%2  = StrideArraysCore.boundscheck()::Core.Const(false)
└──       goto #3 if not %2
2 ─       Core.Const(:(goto %6 if not $(Expr(:boundscheck))))
│         Core.Const(:(StrideArraysCore.checkbounds(A, i)))
└──       Core.Const(:(goto %7))
3%7  = StrideArraysCore.pointer(A)::Ptr{Int64}%8  = StaticArrayInterface.offset1::Core.Const(StaticArrayInterface.offset1)
│   %9  = (%8)(A)::Core.Const(static(1))
│   %10 = (i - %9)::Any%11 = LayoutPointers.bytestrides::Core.Const(LayoutPointers.bytestrides)
│   %12 = (%11)(A)::Core.Const((static(8),))
│   %13 = StrideArraysCore.only(%12)::Core.Const(static(8))
│   %14 = (%10 * %13)::Any%15 = (%7 + %14)::Any%16 = StrideArraysCore.pload(%15)::Any
└──       return %16

This does not appear to happen with Julia v1.9 or without using --check-bounds=no:

`julia-1.10 mwe.jl`
MethodInstance for getindex(::PtrArray{Int64, 1, (1,), Tuple{Int64}, Tuple{Nothing}, Tuple{StaticInt{1}}}, ::Int64)
  from getindex(A::PtrArray{T, 1}, i::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, StaticInt}) where T @ StrideArraysCore ~/.julia/packages/StrideArraysCore/COJRJ/src/ptr_array.jl:957
Static Parameters
  T = Int64
Arguments
  #self#::Core.Const(getindex)
  A::PtrArray{Int64, 1, (1,), Tuple{Int64}, Tuple{Nothing}, Tuple{StaticInt{1}}}
  i::Int64
Body::Int64
1nothing%2  = StrideArraysCore.boundscheck()::Core.Const(false)
└──       goto #3 if not %2
2 ─       Core.Const(:(goto %6 if not $(Expr(:boundscheck))))
│         Core.Const(:(StrideArraysCore.checkbounds(A, i)))
└──       Core.Const(:(goto %7))
3%7  = StrideArraysCore.pointer(A)::Ptr{Int64}%8  = StaticArrayInterface.offset1::Core.Const(StaticArrayInterface.offset1)
│   %9  = (%8)(A)::Core.Const(static(1))
│   %10 = (i - %9)::Int64%11 = LayoutPointers.bytestrides::Core.Const(LayoutPointers.bytestrides)
│   %12 = (%11)(A)::Core.Const((static(8),))
│   %13 = StrideArraysCore.only(%12)::Core.Const(static(8))
│   %14 = (%10 * %13)::Int64%15 = (%7 + %14)::Ptr{Int64}%16 = StrideArraysCore.pload(%15)::Int64
└──       return %16
`julia-1.9 --check-bounds=no mwe.jl`
MethodInstance for getindex(::PtrArray{Int64, 1, (1,), Tuple{Int64}, Tuple{Nothing}, Tuple{StaticInt{1}}}, ::Int64)
  from getindex(A::PtrArray{T, 1}, i::Union{Int128, Int16, Int32, Int64, Int8, UInt128, UInt16, UInt32, UInt64, UInt8, StaticInt}) where T @ StrideArraysCore ~/.julia/packages/StrideArraysCore/COJRJ/src/ptr_array.jl:957
Static Parameters
  T = Int64
Arguments
  #self#::Core.Const(getindex)
  A::PtrArray{Int64, 1, (1,), Tuple{Int64}, Tuple{Nothing}, Tuple{StaticInt{1}}}
  i::Int64
Body::Int64
1nothing%2  = StrideArraysCore.boundscheck()::Core.Const(false)
└──       goto #3 if not %2
2 ─       Core.Const(:(goto %6 if not $(Expr(:boundscheck))))
│         Core.Const(:(StrideArraysCore.checkbounds(A, i)))
└──       Core.Const(:(goto %7))
3%7  = StrideArraysCore.pointer(A)::Ptr{Int64}%8  = StaticArrayInterface.offset1::Core.Const(StaticArrayInterface.offset1)
│   %9  = (%8)(A)::Core.Const(static(1))
│   %10 = (i - %9)::Int64%11 = LayoutPointers.bytestrides::Core.Const(LayoutPointers.bytestrides)
│   %12 = (%11)(A)::Core.Const((static(8),))
│   %13 = StrideArraysCore.only(%12)::Core.Const(static(8))
│   %14 = (%10 * %13)::Int64%15 = (%7 + %14)::Ptr{Int64}%16 = StrideArraysCore.pload(%15)::Int64
└──       return %16

Unfortunately, this regression makes StrideArrays.jl currently unusably slow on Julia v1.10 with bounds checking disabled globally.

cc @ranocha

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