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

inference: remove special handlings of quasi-builtin functions #48684

Merged
merged 1 commit into from
Feb 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 0 additions & 21 deletions base/compiler/abstractinterpretation.jl
Original file line number Diff line number Diff line change
Expand Up @@ -813,9 +813,6 @@ is_method_pure(match::MethodMatch) = is_method_pure(match.method, match.spec_typ
function pure_eval_call(interp::AbstractInterpreter,
@nospecialize(f), applicable::Vector{Any}, arginfo::ArgInfo)
pure_eval_eligible(interp, f, applicable, arginfo) || return nothing
return _pure_eval_call(f, arginfo)
end
function _pure_eval_call(@nospecialize(f), arginfo::ArgInfo)
args = collect_const_args(arginfo, #=start=#2)
value = try
Core._apply_pure(f, args)
Expand Down Expand Up @@ -2041,26 +2038,8 @@ function abstract_call_known(interp::AbstractInterpreter, @nospecialize(f),
end
argtypes = Any[typeof(<:), argtypes[3], argtypes[2]]
return abstract_call_known(interp, <:, ArgInfo(fargs, argtypes), si, sv, max_methods)
elseif la == 2 &&
(a2 = argtypes[2]; isa(a2, Const)) && (svecval = a2.val; isa(svecval, SimpleVector)) &&
istopfunction(f, :length)
# mark length(::SimpleVector) as @pure
return CallMeta(Const(length(svecval)), EFFECTS_TOTAL, MethodResultPure())
elseif la == 3 &&
(a2 = argtypes[2]; isa(a2, Const)) && (svecval = a2.val; isa(svecval, SimpleVector)) &&
(a3 = argtypes[3]; isa(a3, Const)) && (idx = a3.val; isa(idx, Int)) &&
istopfunction(f, :getindex)
# mark getindex(::SimpleVector, i::Int) as @pure
if 1 <= idx <= length(svecval) && isassigned(svecval, idx)
return CallMeta(Const(getindex(svecval, idx)), EFFECTS_TOTAL, MethodResultPure())
end
elseif la == 2 && istopfunction(f, :typename)
return CallMeta(typename_static(argtypes[2]), EFFECTS_TOTAL, MethodResultPure())
elseif la == 3 && istopfunction(f, :typejoin)
if is_all_const_arg(arginfo, #=start=#2)
val = _pure_eval_call(f, arginfo)
return CallMeta(val === nothing ? Type : val, EFFECTS_TOTAL, MethodResultPure())
end
elseif f === Core._hasmethod
return _hasmethod_tfunc(interp, argtypes, sv)
end
Expand Down
10 changes: 1 addition & 9 deletions base/compiler/ssair/inlining.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1693,14 +1693,6 @@ function linear_inline_eligible(ir::IRCode)
return true
end

# Check for a number of functions known to be pure
function ispuretopfunction(@nospecialize(f))
return istopfunction(f, :typejoin) ||
istopfunction(f, :isbits) ||
istopfunction(f, :isbitstype) ||
istopfunction(f, :promote_type)
end

function early_inline_special_case(
ir::IRCode, stmt::Expr, @nospecialize(type), sig::Signature,
state::InliningState)
Expand All @@ -1714,7 +1706,7 @@ function early_inline_special_case(
if is_pure_intrinsic_infer(f) && intrinsic_nothrow(f, argtypes[2:end])
return SomeCase(quoted(val))
end
elseif ispuretopfunction(f) || contains_is(_PURE_BUILTINS, f)
elseif contains_is(_PURE_BUILTINS, f)
return SomeCase(quoted(val))
elseif contains_is(_EFFECT_FREE_BUILTINS, f)
if _builtin_nothrow(optimizer_lattice(state.interp), f, argtypes[2:end], type)
Expand Down
16 changes: 15 additions & 1 deletion base/essentials.jl
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,19 @@ macro isdefined(s::Symbol)
return Expr(:escape, Expr(:isdefined, s))
end

"""
nameof(m::Module) -> Symbol

Get the name of a `Module` as a [`Symbol`](@ref).

# Examples
```jldoctest
julia> nameof(Base.Broadcast)
:Broadcast
```
"""
nameof(m::Module) = ccall(:jl_module_name, Ref{Symbol}, (Any,), m)

function _is_internal(__module__)
if ccall(:jl_base_relative_to, Any, (Any,), __module__)::Module === Core.Compiler ||
nameof(__module__) === :Base
Expand Down Expand Up @@ -701,8 +714,9 @@ end

# SimpleVector

@eval getindex(v::SimpleVector, i::Int) = Core._svec_ref($(Expr(:boundscheck)), v, i)
@eval getindex(v::SimpleVector, i::Int) = (@_foldable_meta; Core._svec_ref($(Expr(:boundscheck)), v, i))
function length(v::SimpleVector)
@_total_meta
t = @_gc_preserve_begin v
len = unsafe_load(Ptr{Int}(pointer_from_objref(v)))
@_gc_preserve_end t
Expand Down
4 changes: 2 additions & 2 deletions base/promotion.jl
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@ Number
"""
typejoin() = Bottom
typejoin(@nospecialize(t)) = t
typejoin(@nospecialize(t), ts...) = (@_total_meta; typejoin(t, typejoin(ts...)))
typejoin(@nospecialize(t), ts...) = (@_foldable_meta; typejoin(t, typejoin(ts...)))
function typejoin(@nospecialize(a), @nospecialize(b))
@_total_meta
@_foldable_meta
if isa(a, TypeVar)
return typejoin(a.ub, b)
elseif isa(b, TypeVar)
Expand Down
13 changes: 0 additions & 13 deletions base/reflection.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,6 @@

# name and module reflection

"""
nameof(m::Module) -> Symbol

Get the name of a `Module` as a [`Symbol`](@ref).

# Examples
```jldoctest
julia> nameof(Base.Broadcast)
:Broadcast
```
"""
nameof(m::Module) = ccall(:jl_module_name, Ref{Symbol}, (Any,), m)

"""
parentmodule(m::Module) -> Module

Expand Down
24 changes: 24 additions & 0 deletions test/core.jl
Original file line number Diff line number Diff line change
Expand Up @@ -275,6 +275,30 @@ let mi = T26321{3,NTuple{3,Int}}((1,2,3)), mf = T26321{3,NTuple{3,Float64}}((1.0
@test a isa Vector{<:T26321{3}}
end

@test Base.return_types() do
typejoin(Int, UInt)
end |> only == Type{typejoin(Int, UInt)}
@test Base.return_types() do
typejoin(Int, UInt, Float64)
end |> only == Type{typejoin(Int, UInt, Float64)}

let res = @test_throws TypeError let
Base.Experimental.@force_compile
typejoin(1, 2)
nothing
end
err = res.value
@test err.func === :<:
end
let res = @test_throws TypeError let
Base.Experimental.@force_compile
typejoin(1, 2, 3)
nothing
end
err = res.value
@test err.func === :<:
end

# promote_typejoin returns a Union only with Nothing/Missing combined with concrete types
for T in (Nothing, Missing)
@test Base.promote_typejoin(Int, Float64) === Real
Expand Down