Skip to content

Commit 97cf3ef

Browse files
committed
inference: enable evaluation of pure intrinsics
1 parent 6574105 commit 97cf3ef

File tree

2 files changed

+37
-8
lines changed

2 files changed

+37
-8
lines changed

base/inference.jl

+34-8
Original file line numberDiff line numberDiff line change
@@ -1766,6 +1766,12 @@ function builtin_tfunction(@nospecialize(f), argtypes::Array{Any,1},
17661766
return Any
17671767
end
17681768
if isa(f, IntrinsicFunction)
1769+
if is_pure_intrinsic_infer(f) && all(a -> isa(a, Const), argtypes)
1770+
argvals = anymap(a -> a.val, argtypes)
1771+
try
1772+
return Const(f(argvals...))
1773+
end
1774+
end
17691775
iidx = Int(reinterpret(Int32, f::IntrinsicFunction)) + 1
17701776
if iidx < 0 || iidx > length(t_ifunc)
17711777
# invalid intrinsic
@@ -2454,6 +2460,11 @@ function abstract_call(@nospecialize(f), fargs::Union{Tuple{},Vector{Any}}, argt
24542460
end
24552461
return Conditional(a, bty, aty)
24562462
end
2463+
elseif f === (Core.Inference.not_int)
2464+
aty = argtypes[2]
2465+
if isa(aty, Conditional)
2466+
return Conditional(aty.var, aty.elsetype, aty.vtype)
2467+
end
24572468
end
24582469
end
24592470
return isa(rt, TypeVar) ? rt.ub : rt
@@ -4219,23 +4230,38 @@ const _pure_builtins = Any[tuple, svec, fieldtype, apply_type, ===, isa, typeof,
42194230
# known effect-free calls (might not be affect-free)
42204231
const _pure_builtins_volatile = Any[getfield, arrayref, isdefined, Core.sizeof]
42214232

4222-
function is_pure_intrinsic(f::IntrinsicFunction)
4233+
# whether `f` is pure for Inference
4234+
function is_pure_intrinsic_infer(f::IntrinsicFunction)
4235+
return !(f === Intrinsics.pointerref || # this one is volatile
4236+
f === Intrinsics.pointerset || # this one is never effect-free
4237+
f === Intrinsics.llvmcall || # this one is never effect-free
4238+
f === Intrinsics.arraylen || # this one is volatile
4239+
f === Intrinsics.sqrt_llvm || # this one may differ at runtime (by a few ulps)
4240+
f === Intrinsics.cglobal) # cglobal lookup answer changes at runtime
4241+
end
4242+
4243+
# whether `f` is pure for Optimizations
4244+
function is_pure_intrinsic_optim(f::IntrinsicFunction)
42234245
return !(f === Intrinsics.pointerref || # this one is volatile
42244246
f === Intrinsics.pointerset || # this one is never effect-free
42254247
f === Intrinsics.llvmcall || # this one is never effect-free
4226-
f === Intrinsics.checked_sdiv_int ||
4248+
f === Intrinsics.arraylen || # this one is volatile
4249+
f === Intrinsics.checked_sdiv_int || # these may throw errors
42274250
f === Intrinsics.checked_udiv_int ||
42284251
f === Intrinsics.checked_srem_int ||
42294252
f === Intrinsics.checked_urem_int ||
4230-
f === Intrinsics.sqrt_llvm ||
42314253
f === Intrinsics.cglobal) # cglobal throws an error for symbol-not-found
42324254
end
42334255

42344256
function is_pure_builtin(@nospecialize(f))
4235-
return (contains_is(_pure_builtins, f) ||
4236-
contains_is(_pure_builtins_volatile, f) ||
4237-
(isa(f,IntrinsicFunction) && is_pure_intrinsic(f)) ||
4238-
f === return_type)
4257+
if isa(f, IntrinsicFunction)
4258+
return is_pure_intrinsic_optim(f)
4259+
elseif isa(f, Builtin)
4260+
return (contains_is(_pure_builtins, f) ||
4261+
contains_is(_pure_builtins_volatile, f))
4262+
else
4263+
return f === return_type
4264+
end
42394265
end
42404266

42414267
function statement_effect_free(@nospecialize(e), src::CodeInfo, mod::Module)
@@ -4576,7 +4602,7 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
45764602
(isbits(val) && Core.sizeof(val) <= MAX_INLINE_CONST_SIZE &&
45774603
(contains_is(_pure_builtins, f) ||
45784604
(f === getfield && effect_free(e, sv.src, sv.mod, false)) ||
4579-
(isa(f,IntrinsicFunction) && is_pure_intrinsic(f)))))
4605+
(isa(f, IntrinsicFunction) && is_pure_intrinsic_optim(f)))))
45804606
return inline_as_constant(val, argexprs, sv, nothing)
45814607
end
45824608
end

test/inference.jl

+3
Original file line numberDiff line numberDiff line change
@@ -1296,3 +1296,6 @@ end
12961296
f_constant(x) = convert(Int, x)
12971297
g_test_constant() = (f_constant(3) == 3 && f_constant(4) == 4 ? true : "BAD")
12981298
@test @inferred g_test_constant()
1299+
1300+
f_pure_add() = (1 + 1 == 2) ? true : "FAIL"
1301+
@test @inferred f_pure_add()

0 commit comments

Comments
 (0)