diff --git a/base/multidimensional.jl b/base/multidimensional.jl index 0634805fe48742..b3ac26ff4fbb36 100644 --- a/base/multidimensional.jl +++ b/base/multidimensional.jl @@ -349,8 +349,14 @@ module IteratorsMD # AbstractArray implementation Base.axes(iter::CartesianIndices{N,R}) where {N,R} = map(Base.axes1, iter.indices) Base.IndexStyle(::Type{CartesianIndices{N,R}}) where {N,R} = IndexCartesian() - @propagate_inbounds function Base.getindex(iter::CartesianIndices{N,R}, I::Vararg{Int, N}) where {N,R} - CartesianIndex(getindex.(iter.indices, I)) + @inline function Base.getindex(iter::CartesianIndices{N,R}, I::Vararg{Int, N}) where {N,R} + # Eagerly do boundscheck before calculating each item of the CartesianIndex so that + # we can pass `@inbounds` hint to inside the map and generates more efficient SIMD codes (#42115) + @boundscheck checkbounds(iter, I...) + index = map(iter.indices, I) do r, i + @inbounds getindex(r, i) + end + CartesianIndex(index) end ndims(R::CartesianIndices) = ndims(typeof(R)) diff --git a/test/boundscheck_exec.jl b/test/boundscheck_exec.jl index e1a7029334a3da..735cd88c137587 100644 --- a/test/boundscheck_exec.jl +++ b/test/boundscheck_exec.jl @@ -259,4 +259,17 @@ if bc_opt == bc_default || bc_opt == bc_off @test !occursin("arrayref(true", typed_40281) end +@testset "pass inbounds meta to getindex on CartesianIndices (#42115)" begin + @inline getindex_42115(r, i, j) = @inbounds getindex(r, i, j) + + R = CartesianIndices((5, 5)) + if bc_opt == bc_on + @test_throws BoundsError getindex_42115(R, -1, -1) + @test_throws BoundsError getindex_42115(R, 1, -1) + else + @test getindex_42115(R, -1, -1) == CartesianIndex(-1, -1) + @test getindex_42115(R, 1, -1) == CartesianIndex(1, -1) + end +end + end