Skip to content

Commit 7b83a9c

Browse files
yuyichaojeffwong
authored andcommitted
Allow inlining of constant return value of isdefined
1 parent ebf3279 commit 7b83a9c

File tree

2 files changed

+31
-15
lines changed

2 files changed

+31
-15
lines changed

base/inference.jl

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -602,6 +602,10 @@ function isdefined_tfunc(args...)
602602
return Const(true)
603603
elseif idx <= 0 || (!isvatuple(a1) && idx > fieldcount(a1))
604604
return Const(false)
605+
elseif !isvatuple(a1) && isbits(fieldtype(a1, idx))
606+
return Const(true)
607+
elseif isa(arg1, Const) && isimmutable((arg1::Const).val)
608+
return Const(isdefined((arg1::Const).val, idx))
605609
end
606610
end
607611
end
@@ -4084,7 +4088,7 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
40844088
if isa(e.typ, Const) # || isconstType(e.typ)
40854089
val = e.typ.val
40864090
if (f === apply_type || f === fieldtype || f === typeof || f === (===) ||
4087-
f === Core.sizeof ||
4091+
f === Core.sizeof || f === isdefined ||
40884092
istopfunction(topmod, f, :typejoin) ||
40894093
istopfunction(topmod, f, :isbits) ||
40904094
istopfunction(topmod, f, :promote_type) ||

test/inference.jl

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,46 +1011,58 @@ function test_const_return(@nospecialize(f), @nospecialize(t), @nospecialize(val
10111011
end
10121012
end
10131013

1014-
test_const_return(()->1, Tuple{}, 1)
1015-
test_const_return(()->sizeof(Int), Tuple{}, sizeof(Int))
1016-
test_const_return(()->sizeof(1), Tuple{}, sizeof(Int))
1017-
test_const_return(()->sizeof(DataType), Tuple{}, sizeof(DataType))
1018-
test_const_return(()->sizeof(1 < 2), Tuple{}, 1)
1019-
@eval test_const_return(()->Core.sizeof($(Array{Int}())), Tuple{}, sizeof(Int))
1020-
@eval test_const_return(()->Core.sizeof($(Matrix{Float32}(2, 2))), Tuple{}, 4 * 2 * 2)
1021-
1022-
function find_core_sizeof_call(code)
1014+
function find_call(code, func, narg)
10231015
for ex in code
10241016
isa(ex, Expr) || continue
10251017
ex = ex::Expr
1026-
if ex.head === :call && length(ex.args) == 2
1027-
if ex.args[1] === Core.sizeof || ex.args[1] == GlobalRef(Core, :sizeof)
1018+
if ex.head === :call && length(ex.args) == narg
1019+
farg = ex.args[1]
1020+
if isa(farg, GlobalRef)
1021+
farg = farg::GlobalRef
1022+
if isdefined(farg.mod, farg.name) && isconst(farg.mod, farg.name)
1023+
farg = getfield(farg.mod, farg.name)
1024+
end
1025+
end
1026+
if farg === func
10281027
return true
10291028
end
10301029
elseif Core.Inference.is_meta_expr(ex)
10311030
continue
10321031
end
1033-
find_core_sizeof_call(ex.args) && return true
1032+
find_call(ex.args, func, narg) && return true
10341033
end
10351034
return false
10361035
end
10371036

1037+
test_const_return(()->1, Tuple{}, 1)
1038+
test_const_return(()->sizeof(Int), Tuple{}, sizeof(Int))
1039+
test_const_return(()->sizeof(1), Tuple{}, sizeof(Int))
1040+
test_const_return(()->sizeof(DataType), Tuple{}, sizeof(DataType))
1041+
test_const_return(()->sizeof(1 < 2), Tuple{}, 1)
1042+
@eval test_const_return(()->Core.sizeof($(Array{Int}())), Tuple{}, sizeof(Int))
1043+
@eval test_const_return(()->Core.sizeof($(Matrix{Float32}(2, 2))), Tuple{}, 4 * 2 * 2)
1044+
10381045
# Make sure Core.sizeof with a ::DataType as inferred input type is inferred but not constant.
10391046
function sizeof_typeref(typeref)
10401047
Core.sizeof(typeref[])
10411048
end
10421049
@test @inferred(sizeof_typeref(Ref{DataType}(Int))) == sizeof(Int)
1043-
@test find_core_sizeof_call(first(@code_typed sizeof_typeref(Ref{DataType}())).code)
1050+
@test find_call(first(@code_typed sizeof_typeref(Ref{DataType}())).code, Core.sizeof, 2)
10441051
# Constant `Vector` can be resized and shouldn't be optimized to a constant.
10451052
const constvec = [1, 2, 3]
10461053
@eval function sizeof_constvec()
10471054
Core.sizeof($constvec)
10481055
end
10491056
@test @inferred(sizeof_constvec()) == sizeof(Int) * 3
1050-
@test find_core_sizeof_call(first(@code_typed sizeof_constvec()).code)
1057+
@test find_call(first(@code_typed sizeof_constvec()).code, Core.sizeof, 2)
10511058
push!(constvec, 10)
10521059
@test @inferred(sizeof_constvec()) == sizeof(Int) * 4
10531060

1061+
test_const_return((x)->isdefined(x, :re), Tuple{Complex128}, true)
1062+
isdefined_f3(x) = isdefined(x, 3)
1063+
@test @inferred(isdefined_f3(())) == false
1064+
@test find_call(first(code_typed(isdefined_f3, Tuple{Tuple{Vararg{Int}}})[1]).code, isdefined, 3)
1065+
10541066
let isa_tfunc = Core.Inference.t_ffunc_val[
10551067
findfirst(Core.Inference.t_ffunc_key, isa)][3]
10561068
@test isa_tfunc(Array, Const(AbstractArray)) === Const(true)

0 commit comments

Comments
 (0)