From babc5d368b12b072dcba6989176740e3a12e3f6a Mon Sep 17 00:00:00 2001 From: Shuhei Kadowaki Date: Thu, 16 Feb 2023 02:11:33 +0900 Subject: [PATCH] inference: remove special handlings of quasi-builtin functions And fix their effect modeling. --- base/compiler/abstractinterpretation.jl | 21 --------------------- base/compiler/ssair/inlining.jl | 10 +--------- base/essentials.jl | 16 +++++++++++++++- base/promotion.jl | 4 ++-- base/reflection.jl | 13 ------------- test/core.jl | 24 ++++++++++++++++++++++++ 6 files changed, 42 insertions(+), 46 deletions(-) diff --git a/base/compiler/abstractinterpretation.jl b/base/compiler/abstractinterpretation.jl index b6d1fea655e89..9a4859682cf31 100644 --- a/base/compiler/abstractinterpretation.jl +++ b/base/compiler/abstractinterpretation.jl @@ -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) @@ -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 diff --git a/base/compiler/ssair/inlining.jl b/base/compiler/ssair/inlining.jl index e7fa8856c6101..486f5b2c0c625 100644 --- a/base/compiler/ssair/inlining.jl +++ b/base/compiler/ssair/inlining.jl @@ -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) @@ -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) diff --git a/base/essentials.jl b/base/essentials.jl index 14ccce0d125fb..08454a800d171 100644 --- a/base/essentials.jl +++ b/base/essentials.jl @@ -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 @@ -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 diff --git a/base/promotion.jl b/base/promotion.jl index fb5c5b83864ae..993f0be6c0924 100644 --- a/base/promotion.jl +++ b/base/promotion.jl @@ -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) diff --git a/base/reflection.jl b/base/reflection.jl index 22c4698e5c31c..9e2615a16a190 100644 --- a/base/reflection.jl +++ b/base/reflection.jl @@ -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 diff --git a/test/core.jl b/test/core.jl index adf895ba471ea..f1a7c3fafeab3 100644 --- a/test/core.jl +++ b/test/core.jl @@ -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