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

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

Open
sloede opened this issue Aug 19, 2023 · 2 comments

Comments

@sloede
Copy link

sloede commented Aug 19, 2023

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

@chriselrod
Copy link
Member

PRs welcome.

│   %9  = (%8)(A)::Core.Const(static(1))
│   %10 = (i - %9)::Any

For starters, %9 has no reason to be a static Int. Maybe convert to Int first?
Or, perhaps look at that for a more minimal example.

@sloede
Copy link
Author

sloede commented Aug 20, 2023

@ranocha made it a more minimum MWE and it turns out it is not related to StrideArrays.jl but rather Static.jl and Base.promote_type, so we reported a more focused example in JuliaLang/julia#50985.

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