From cd959a25e0eebcda0406573def0ec401caacde15 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Wed, 12 Jul 2017 11:15:59 -0400 Subject: [PATCH] fix isa tfunc for type kinds previously, isa_tfunc(DataType, Type{...}) might return Const(false) --- base/inference.jl | 34 +++++++++++++++++++--------------- test/inference.jl | 35 ++++++++++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/base/inference.jl b/base/inference.jl index 093908ebec6b2..3cdb8a4798594 100644 --- a/base/inference.jl +++ b/base/inference.jl @@ -378,19 +378,21 @@ isType(t::ANY) = isa(t, DataType) && (t::DataType).name === _Type_name # true if Type is inlineable as constant (is a singleton) isconstType(t::ANY) = isType(t) && (isleaftype(t.parameters[1]) || t.parameters[1] === Union{}) +iskindtype(t::ANY) = (t === DataType || t === UnionAll || t === Union || t === typeof(Bottom)) + const IInf = typemax(Int) # integer infinity -const n_ifunc = reinterpret(Int32,arraylen)+1 -const t_ifunc = Array{Tuple{Int,Int,Any},1}(n_ifunc) -const t_ifunc_cost = Array{Int,1}(n_ifunc) -const t_ffunc_key = Array{Function,1}(0) -const t_ffunc_val = Array{Tuple{Int,Int,Any},1}(0) -const t_ffunc_cost = Array{Int,1}(0) +const n_ifunc = reinterpret(Int32, arraylen) + 1 +const t_ifunc = Array{Tuple{Int, Int, Any}, 1}(n_ifunc) +const t_ifunc_cost = Array{Int, 1}(n_ifunc) +const t_ffunc_key = Array{Any, 1}(0) +const t_ffunc_val = Array{Tuple{Int, Int, Any}, 1}(0) +const t_ffunc_cost = Array{Int, 1}(0) function add_tfunc(f::IntrinsicFunction, minarg::Int, maxarg::Int, tfunc::ANY, cost::Int) - idx = reinterpret(Int32,f)+1 + idx = reinterpret(Int32, f) + 1 t_ifunc[idx] = (minarg, maxarg, tfunc) t_ifunc_cost[idx] = cost end -function add_tfunc(f::Function, minarg::Int, maxarg::Int, tfunc::ANY, cost::Int) +function add_tfunc(#=@nospecialize::Builtin=# f::Function, minarg::Int, maxarg::Int, tfunc::ANY, cost::Int) push!(t_ffunc_key, f) push!(t_ffunc_val, (minarg, maxarg, tfunc)) push!(t_ffunc_cost, cost) @@ -711,7 +713,7 @@ add_tfunc(isa, 2, 2, if t !== Any && !has_free_typevars(t) if v ⊑ t return Const(true) - elseif isa(v, Const) || isa(v, Conditional) || isleaftype(v) + elseif isa(v, Const) || isa(v, Conditional) || (isleaftype(v) && !iskindtype(v)) return Const(false) end end @@ -1501,20 +1503,20 @@ function builtin_tfunction(f::ANY, argtypes::Array{Any,1}, end if isa(f, IntrinsicFunction) iidx = Int(reinterpret(Int32, f::IntrinsicFunction)) + 1 - if !isassigned(t_ifunc, iidx) - # unknown/unhandled intrinsic (most fall in this category since most return an unboxed value) + if iidx < 0 || iidx > length(t_ifunc) + # invalid intrinsic return Any end tf = t_ifunc[iidx] else - fidx = findfirst(t_ffunc_key, f::Function) + fidx = findfirst(t_ffunc_key, f) if fidx == 0 - # unknown/unhandled builtin or anonymous function + # unknown/unhandled builtin function return Any end tf = t_ffunc_val[fidx] end - tf = tf::Tuple{Real, Real, Any} + tf = tf::Tuple{Int, Int, Any} if !(tf[1] <= length(argtypes) <= tf[2]) # wrong # of args return Bottom @@ -4640,7 +4642,7 @@ function statement_cost(ex::Expr, src::CodeInfo, mod::Module, params::InferenceP elseif f == Main.Core.arrayref return plus_saturate(argcost, isknowntype(ex.typ) ? 4 : params.inline_nonleaf_penalty) end - fidx = findfirst(t_ffunc_key, f::Function) + fidx = findfirst(t_ffunc_key, f) if fidx == 0 # unknown/unhandled builtin or anonymous function # Use the generic cost of a direct function call @@ -5906,6 +5908,8 @@ let fs = Any[typeinf_ext, typeinf, typeinf_edge, occurs_outside_getfield, pure_e if isassigned(t_ifunc, i) x = t_ifunc[i] push!(fs, x[3]) + else + println(STDERR, "WARNING: tfunc missing for ", reinterpret(IntrinsicFunction, Int32(i))) end end for f in fs diff --git a/test/inference.jl b/test/inference.jl index c0b10a6c7ac68..1a28b1f6425ad 100644 --- a/test/inference.jl +++ b/test/inference.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license # tests for Core.Inference correctness and precision +import Core.Inference: Const, Conditional, ⊑ # issue 9770 @noinline x9770() = false @@ -877,7 +878,7 @@ let f(x) = isdefined(x, :NonExistentField) ? 1 : "" @test Base.return_types(f, (Complex64,)) == Any[String] @test Union{Int,String} <: Base.return_types(f, (AbstractArray,))[1] end -import Core.Inference: Const, isdefined_tfunc, ⊑ +import Core.Inference: isdefined_tfunc @test isdefined_tfunc(Complex64, Const(())) === Union{} @test isdefined_tfunc(Complex64, Const(1)) === Const(true) @test isdefined_tfunc(Complex64, Const(2)) === Const(true) @@ -1049,3 +1050,35 @@ end @test find_core_sizeof_call(first(@code_typed sizeof_constvec()).code) push!(constvec, 10) @test @inferred(sizeof_constvec()) == sizeof(Int) * 4 + +let isa_tfunc = Core.Inference.t_ffunc_val[ + findfirst(Core.Inference.t_ffunc_key, isa)][3] + @test isa_tfunc(Array, Const(AbstractArray)) === Const(true) + @test isa_tfunc(Array, Type{AbstractArray}) === Const(true) + @test isa_tfunc(Array, Type{AbstractArray{Int}}) == Bool + @test isa_tfunc(Array{Real}, Type{AbstractArray{Int}}) === Bool # could be improved + @test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Real, 2})) === Const(true) + @test isa_tfunc(Array{Real, 2}, Const(AbstractArray{Int, 2})) === Const(false) + @test isa_tfunc(DataType, Int) === Bool # could be improved + @test isa_tfunc(DataType, Const(Type{Int})) === Bool + @test isa_tfunc(DataType, Const(Type{Array})) === Bool + @test isa_tfunc(UnionAll, Const(Type{Int})) === Bool # could be improved + @test isa_tfunc(UnionAll, Const(Type{Array})) === Bool + @test isa_tfunc(Union, Const(Union{Float32, Float64})) === Bool + @test isa_tfunc(Union, Type{Union}) === Const(true) + @test isa_tfunc(typeof(Union{}), Const(Int)) === Bool # any result is ok + @test isa_tfunc(typeof(Union{}), Const(Union{})) === Bool # could be improved + @test isa_tfunc(typeof(Union{}), typeof(Union{})) === Bool # could be improved + @test isa_tfunc(typeof(Union{}), Union{}) === Bool # could be improved + @test isa_tfunc(typeof(Union{}), Type{typeof(Union{})}) === Const(true) + @test isa_tfunc(typeof(Union{}), Const(typeof(Union{}))) === Const(true) + let c = Conditional(Core.SlotNumber(0), Const(Union{}), Const(Union{})) + @test isa_tfunc(c, Const(Bool)) === Const(true) + @test isa_tfunc(c, Type{Bool}) === Const(true) + @test isa_tfunc(c, Const(Real)) === Const(true) + @test isa_tfunc(c, Type{Real}) === Const(true) + @test isa_tfunc(c, Const(Signed)) === Const(false) + @test isa_tfunc(c, Type{Complex}) === Const(false) + @test isa_tfunc(c, Type{Complex{T}} where T) === Const(false) + end +end