Bound checking in eachindex(x,y) in 1.7.3

I noticed now that in 1.7.3 a code like this does not skip bounds checking:

julia> function f!(x,y)
           for i in eachindex(x,y)
               x[i] = x[i] + y[i]
           end
       end
f! (generic function with 1 method)

julia> x = rand(10^5); y = rand(10^5);

julia> @btime f!($x,$y)
  53.200 μs (0 allocations: 0 bytes)

vs.

julia> function f!(x,y)
           for i in eachindex(x,y)
               @inbounds x[i] = x[i] + y[i]
           end
       end
f! (generic function with 1 method)

julia> @btime f!($x,$y)
  28.550 μs (0 allocations: 0 bytes)

But it does in 1.8-rc1:

julia> function f!(x,y)
           for i in eachindex(x,y)
               x[i] = x[i] + y[i]
           end
       end
f! (generic function with 1 method)

julia> x = rand(10^5); y = rand(10^5);

julia> @btime f!($x,$y)
  29.804 μs (0 allocations: 0 bytes)

I don’t really have a question, I just thought this was sorted out by the compiler long ago. Since this seems to be only recently supported by the compiler, is there anything related we should aware about in terms of performance and best coding style? (I was just happy getting rid of all @inbounds in some code of mine, but I’ll wait for the next LTS now :slight_smile: ).

There might be other issues as well, e.g. regression on inferring inbounds for `eachindex()` · Issue #45507 · JuliaLang/julia · GitHub. Not using @inbounds sometimes makes llvm emit subpar code, even on 1.9 on a commonly used CPU. The issue might not even be bounds-checking.

1 Like

In my example the native code appears to be bounds-checking in 1.7.3, as it shows lines like this:

	movabsq	$jl_bounds_error_ints, %rax

which are not present in the 1.8-rc1 native code. (although my understanding of native code is minimal)