Skip to content

Commit

Permalink
a few compiler improvements (#36176)
Browse files Browse the repository at this point in the history
- improve fieldtype_nothrow for vararg tuple types
- remove UnionAll construction code from tuple_type_head
- add specializations to avoid some common generated functions
  • Loading branch information
JeffBezanson authored Jun 8, 2020
1 parent 98e678f commit 9d4565b
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 10 deletions.
8 changes: 4 additions & 4 deletions base/compiler/tfuncs.jl
Original file line number Diff line number Diff line change
Expand Up @@ -876,12 +876,12 @@ function _fieldtype_nothrow(@nospecialize(s), exact::Bool, name::Const)
isa(fld, Int) || return false
ftypes = datatype_fieldtypes(u)
nf = length(ftypes)
(fld >= 1 && fld <= nf) || return false
if u.name === Tuple.name && fld >= nf && isvarargtype(ftypes[nf])
# The length of the tuple will be determined at runtime, we can't say
# anything
return false
# If we don't know the exact type, the length of the tuple will be determined
# at runtime and we can't say anything.
return exact
end
(fld >= 1 && fld <= nf) || return false
return true
end

Expand Down
2 changes: 1 addition & 1 deletion base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -205,7 +205,7 @@ ERROR: ArgumentError: Cannot call tail on an empty tuple.
tail(x::Tuple) = argtail(x...)
tail(::Tuple{}) = throw(ArgumentError("Cannot call tail on an empty tuple."))

tuple_type_head(T::Type) = (@_pure_meta; fieldtype(T::Type{<:Tuple}, 1))
tuple_type_head(T::Type) = (@_pure_meta; fieldtype(T, 1))

function tuple_type_tail(T::Type)
@_pure_meta
Expand Down
32 changes: 28 additions & 4 deletions base/multidimensional.jl
Original file line number Diff line number Diff line change
Expand Up @@ -758,8 +758,7 @@ function _unsafe_getindex(::IndexStyle, A::AbstractArray, I::Vararg{Union{Real,
return dest
end

# Always index with the exactly indices provided.
@generated function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray}, N}) where N
function _generate_unsafe_getindex!_body(N::Int)
quote
@_inline_meta
D = eachindex(dest)
Expand All @@ -776,6 +775,20 @@ end
end
end

# Always index with the exactly indices provided.
@generated function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray}, N}) where N
_generate_unsafe_getindex!_body(N)
end

# manually written-out specializations for 1 and 2 arguments to save compile time
@eval function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray},1})
$(_generate_unsafe_getindex!_body(1))
end

@eval function _unsafe_getindex!(dest::AbstractArray, src::AbstractArray, I::Vararg{Union{Real, AbstractArray},2})
$(_generate_unsafe_getindex!_body(2))
end

@noinline throw_checksize_error(A, sz) = throw(DimensionMismatch("output array is the wrong size; expected $sz, got $(size(A))"))

## setindex! ##
Expand All @@ -786,8 +799,7 @@ function _setindex!(l::IndexStyle, A::AbstractArray, x, I::Union{Real, AbstractA
A
end

@generated function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Union{Real,AbstractArray}...)
N = length(I)
function _generate_unsafe_setindex!_body(N::Int)
quote
x′ = unalias(A, x)
@nexprs $N d->(I_d = unalias(A, I[d]))
Expand All @@ -806,6 +818,18 @@ end
end
end

@generated function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Vararg{Union{Real,AbstractArray}, N}) where N
_generate_unsafe_setindex!_body(N)
end

@eval function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Vararg{Union{Real,AbstractArray},1})
$(_generate_unsafe_setindex!_body(1))
end

@eval function _unsafe_setindex!(::IndexStyle, A::AbstractArray, x, I::Vararg{Union{Real,AbstractArray},2})
$(_generate_unsafe_setindex!_body(2))
end

diff(a::AbstractVector) = diff(a, dims=1)

"""
Expand Down
6 changes: 5 additions & 1 deletion base/namedtuple.jl
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,9 @@ function merge(a::NamedTuple{an}, b::NamedTuple{bn}) where {an, bn}
end
end

merge(a::NamedTuple{()}, b::NamedTuple) = b
merge(a::NamedTuple, b::NamedTuple{()}) = a
merge(a::NamedTuple{()}, b::NamedTuple{()}) = a
merge(a::NamedTuple{()}, b::NamedTuple) = b

merge(a::NamedTuple, b::Iterators.Pairs{<:Any,<:Any,<:Any,<:NamedTuple}) = merge(a, b.data)

Expand Down Expand Up @@ -320,6 +322,8 @@ function structdiff(a::NamedTuple{an}, b::Union{NamedTuple{bn}, Type{NamedTuple{
end
end

structdiff(a::NamedTuple{an}, b::Union{NamedTuple{an}, Type{NamedTuple{an}}}) where {an} = (;)

"""
setindex(nt::NamedTuple, val, key::Symbol)
Expand Down
3 changes: 3 additions & 0 deletions test/compiler/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -655,6 +655,9 @@ let fieldtype_tfunc = Core.Compiler.fieldtype_tfunc,
@test fieldtype_nothrow(Union{Type{Base.RefValue{<:Real}}, Type{Base.RefValue{Any}}}, Const(:x))
@test fieldtype_nothrow(Const(Union{Base.RefValue{<:Real}, Base.RefValue{Any}}), Const(:x))
@test fieldtype_nothrow(Type{Union{Base.RefValue{T}, Base.RefValue{Any}}} where {T<:Real}, Const(:x))
@test fieldtype_nothrow(Type{Tuple{Vararg{Int}}}, Const(1))
@test fieldtype_nothrow(Type{Tuple{Vararg{Int}}}, Const(42))
@test !fieldtype_nothrow(Type{<:Tuple{Vararg{Int}}}, Const(1))
end

# issue #11480
Expand Down

2 comments on commit 9d4565b

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Executing the daily benchmark build, I will reply here when finished:

@nanosoldier runbenchmarks(ALL, isdaily = true)

@nanosoldier
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan

Please sign in to comment.