@@ -539,4 +539,30 @@ ndims_index(@nospecialize T::Type{<:Base.LogicalIndex}) = ndims(fieldtype(T, :ma
539539ndims_index (T:: DataType ) = 1
540540ndims_index (@nospecialize (i)) = ndims_index (typeof (i))
541541
542+ """
543+ instances_do_not_alias(::Type{T}) -> Bool
544+
545+ Is it safe to `ivdep` arrays containing elements of type `T`?
546+ That is, would it be safe to write to an array full of `T` in parallel?
547+ This is not true for `mutable struct`s in general, where editing one index
548+ could edit other indices.
549+ That is, it is not safe when different instances may alias the same memory.
550+ """
551+ instances_do_not_alias (:: Type{T} ) where {T} = Base. isbitstype (T)
552+
553+ """
554+ indices_do_not_alias(::Type{T<:AbstractArray}) -> Bool
555+
556+ Is it safe to `ivdep` arrays of type `T`?
557+ That is, would it be safe to write to an array of type `T` in parallel?
558+ Examples where this is not true are `BitArray`s or `view(rand(6), [1,2,3,1,2,3])`.
559+ That is, it is not safe whenever different indices may alias the same memory.
560+ """
561+ indices_do_not_alias (:: Type ) = false
562+ indices_do_not_alias (:: Type{A} ) where {T, A<: Base.StridedArray{T} } = instances_do_not_alias (T)
563+ indices_do_not_alias (:: Type{Adjoint{T,A}} ) where {T, A <: AbstractArray{T} } = indices_do_not_alias (A)
564+ indices_do_not_alias (:: Type{Transpose{T,A}} ) where {T, A <: AbstractArray{T} } = indices_do_not_alias (A)
565+ indices_do_not_alias (:: Type{<:SubArray{<:Any,<:Any,A,I}} ) where {
566+ A,I<: Tuple{Vararg{Union{Base.RangeIndex, Base.ReshapedUnitRange, Base.AbstractCartesianIndex}}} } = indices_do_not_alias (A)
567+
542568end # module
0 commit comments