Skip to content

Commit 412c4de

Browse files
committed
inference: enable evaluation of pure intrinsics
1 parent 7f8ae7f commit 412c4de

File tree

2 files changed

+32
-8
lines changed

2 files changed

+32
-8
lines changed

base/inference.jl

+29-8
Original file line numberDiff line numberDiff line change
@@ -1768,6 +1768,12 @@ function builtin_tfunction(@nospecialize(f), argtypes::Array{Any,1},
17681768
return Any
17691769
end
17701770
if isa(f, IntrinsicFunction)
1771+
if is_pure_intrinsic_infer(f) && all(a -> isa(a, Const), argtypes)
1772+
argvals = anymap(a -> a.val, argtypes)
1773+
try
1774+
return Const(f(argvals...))
1775+
end
1776+
end
17711777
iidx = Int(reinterpret(Int32, f::IntrinsicFunction)) + 1
17721778
if iidx < 0 || iidx > length(t_ifunc)
17731779
# invalid intrinsic
@@ -4235,23 +4241,38 @@ const _pure_builtins = Any[tuple, svec, fieldtype, apply_type, ===, isa, typeof,
42354241
# known effect-free calls (might not be affect-free)
42364242
const _pure_builtins_volatile = Any[getfield, arrayref, isdefined, Core.sizeof]
42374243

4238-
function is_pure_intrinsic(f::IntrinsicFunction)
4244+
# whether `f` is pure for Inference
4245+
function is_pure_intrinsic_infer(f::IntrinsicFunction)
4246+
return !(f === Intrinsics.pointerref || # this one is volatile
4247+
f === Intrinsics.pointerset || # this one is never effect-free
4248+
f === Intrinsics.llvmcall || # this one is never effect-free
4249+
f === Intrinsics.arraylen || # this one is volatile
4250+
f === Intrinsics.sqrt_llvm || # this one may differ at runtime (by a few ulps)
4251+
f === Intrinsics.cglobal) # cglobal lookup answer changes at runtime
4252+
end
4253+
4254+
# whether `f` is pure for Optimizations
4255+
function is_pure_intrinsic_optim(f::IntrinsicFunction)
42394256
return !(f === Intrinsics.pointerref || # this one is volatile
42404257
f === Intrinsics.pointerset || # this one is never effect-free
42414258
f === Intrinsics.llvmcall || # this one is never effect-free
4242-
f === Intrinsics.checked_sdiv_int ||
4259+
f === Intrinsics.arraylen || # this one is volatile
4260+
f === Intrinsics.checked_sdiv_int || # these may throw errors
42434261
f === Intrinsics.checked_udiv_int ||
42444262
f === Intrinsics.checked_srem_int ||
42454263
f === Intrinsics.checked_urem_int ||
4246-
f === Intrinsics.sqrt_llvm ||
42474264
f === Intrinsics.cglobal) # cglobal throws an error for symbol-not-found
42484265
end
42494266

42504267
function is_pure_builtin(@nospecialize(f))
4251-
return (contains_is(_pure_builtins, f) ||
4252-
contains_is(_pure_builtins_volatile, f) ||
4253-
(isa(f,IntrinsicFunction) && is_pure_intrinsic(f)) ||
4254-
f === return_type)
4268+
if isa(f, IntrinsicFunction)
4269+
return is_pure_intrinsic_optim(f)
4270+
elseif isa(f, Builtin)
4271+
return (contains_is(_pure_builtins, f) ||
4272+
contains_is(_pure_builtins_volatile, f))
4273+
else
4274+
return f === return_type
4275+
end
42554276
end
42564277

42574278
function statement_effect_free(@nospecialize(e), src::CodeInfo, mod::Module)
@@ -4592,7 +4613,7 @@ function inlineable(@nospecialize(f), @nospecialize(ft), e::Expr, atypes::Vector
45924613
(isbits(val) && Core.sizeof(val) <= MAX_INLINE_CONST_SIZE &&
45934614
(contains_is(_pure_builtins, f) ||
45944615
(f === getfield && effect_free(e, sv.src, sv.mod, false)) ||
4595-
(isa(f,IntrinsicFunction) && is_pure_intrinsic(f)))))
4616+
(isa(f, IntrinsicFunction) && is_pure_intrinsic_optim(f)))))
45964617
return inline_as_constant(val, argexprs, sv, nothing)
45974618
end
45984619
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)