Skip to content

Commit 3b71aa3

Browse files
committed
inference: Add some basic inference for PhiNode
PhiNode isn't really supported in lowered IR, but it is convenient to be able to emit it, particularly for code that is designed to perform transformations both on typed and on lowered IR (such as Diffractor). Moreover, we do actually supported phinodes in untyped IR both in the interpreter and in the compiler. At the moment, inference assumes that PhiNodes get treated as embedded constants, which is just not what the actual implementation does. At the very least, it should just leave PhiNodes alone in case they accidentally end up in lowered IR (rather than causing crashes), but we might as well give them some basic support.
1 parent 82784fe commit 3b71aa3

File tree

3 files changed

+45
-0
lines changed

3 files changed

+45
-0
lines changed

base/compiler/abstractinterpretation.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1413,6 +1413,13 @@ end
14131413

14141414
function abstract_eval_statement(interp::AbstractInterpreter, @nospecialize(e), vtypes::VarTable, sv::InferenceState)
14151415
if !isa(e, Expr)
1416+
if isa(e, PhiNode)
1417+
rt = Union{}
1418+
for val in e.values
1419+
rt = tmerge(rt, abstract_eval_special_value(interp, val, vtypes, sv))
1420+
end
1421+
return rt
1422+
end
14161423
return abstract_eval_special_value(interp, e, vtypes, sv)
14171424
end
14181425
e = e::Expr

base/compiler/utilities.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,8 @@ function find_ssavalue_uses(body::Vector{Any}, nvals::Int)
267267
push!(uses[e.id], line)
268268
elseif isa(e, Expr)
269269
find_ssavalue_uses(e, uses, line)
270+
elseif isa(e, PhiNode)
271+
find_ssavalue_uses(e, uses, line)
270272
end
271273
end
272274
return uses
@@ -287,6 +289,14 @@ function find_ssavalue_uses(e::Expr, uses::Vector{BitSet}, line::Int)
287289
end
288290
end
289291

292+
function find_ssavalue_uses(e::PhiNode, uses::Vector{BitSet}, line::Int)
293+
for val in e.values
294+
if isa(val, SSAValue)
295+
push!(uses[val.id], line)
296+
end
297+
end
298+
end
299+
290300
function is_throw_call(e::Expr)
291301
if e.head === :call
292302
f = e.args[1]

test/compiler/inference.jl

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3323,3 +3323,31 @@ end |> first === Tuple{Int, String}
33233323
primitive type UInt24ish 24 end
33243324
f34288(x) = Core.Intrinsics.checked_sdiv_int(x, Core.Intrinsics.trunc_int(UInt24ish, 0))
33253325
@test Base.return_types(f34288, (UInt24ish,)) == Any[UInt24ish]
3326+
3327+
# Inference of PhiNode showing up in lowered AST
3328+
function f_convert_me_to_ir(b, x)
3329+
a = b ? sin(x) : cos(x)
3330+
return a
3331+
end
3332+
3333+
let
3334+
# Test the presence of PhiNodes in lowered IR by taking the above function,
3335+
# running it through SSA conversion and then putting it into an opaque
3336+
# closure.
3337+
mi = Core.Compiler.specialize_method(first(methods(f_convert_me_to_ir)),
3338+
Tuple{Bool, Float64}, Core.svec())
3339+
ci = Base.uncompressed_ast(mi.def)
3340+
ci.ssavaluetypes = Any[Any for i = 1:ci.ssavaluetypes]
3341+
sv = Core.Compiler.OptimizationState(mi, Core.Compiler.OptimizationParams(),
3342+
Core.Compiler.NativeInterpreter())
3343+
ir = Core.Compiler.convert_to_ircode(ci, Core.Compiler.copy_exprargs(ci.code),
3344+
false, 2, sv)
3345+
ir = Core.Compiler.slot2reg(ir, ci, 2, sv)
3346+
ir = Core.Compiler.compact!(ir)
3347+
Core.Compiler.replace_code_newstyle!(ci, ir, 3)
3348+
ci.ssavaluetypes = length(ci.code)
3349+
@test any(x->isa(x, Core.PhiNode), ci.code)
3350+
oc = @eval b->$(Expr(:new_opaque_closure, Tuple{Bool, Float64}, false, Any, Any,
3351+
Expr(:opaque_closure_method, nothing, 2, 0, ci)))(b, 1.0)
3352+
@test Base.return_types(oc, Tuple{Bool}) == Any[Float64]
3353+
end

0 commit comments

Comments
 (0)