diff --git a/base/compiler/inferencestate.jl b/base/compiler/inferencestate.jl index 0102f042ba2baf..c2849d88ee06c5 100644 --- a/base/compiler/inferencestate.jl +++ b/base/compiler/inferencestate.jl @@ -685,16 +685,16 @@ _topmod(sv::InferenceState) = _topmod(frame_module(sv)) function record_ssa_assign!(𝕃ᵢ::AbstractLattice, ssa_id::Int, @nospecialize(new), frame::InferenceState) ssavaluetypes = frame.ssavaluetypes old = ssavaluetypes[ssa_id] + if old !== NOT_FOUND + new = tmerge(𝕃ᵢ, new, old) + end if old === NOT_FOUND || !is_lattice_equal(𝕃ᵢ, new, old) ssavaluetypes[ssa_id] = new W = frame.ip for r in frame.ssavalue_uses[ssa_id] if was_reached(frame, r) usebb = block_for_inst(frame.cfg, r) - # We're guaranteed to visit the statement if it's in the current - # basic block, since SSA values can only ever appear after their - # def. - if usebb != frame.currbb + if usebb != frame.currbb || r < ssa_id push!(W, usebb) end end diff --git a/test/compiler/inference.jl b/test/compiler/inference.jl index 30c5c306faa94d..06b5fcb2582fa7 100644 --- a/test/compiler/inference.jl +++ b/test/compiler/inference.jl @@ -5645,3 +5645,31 @@ let t = ntuple(i -> i % 8 == 1 ? Int64 : Float64, 4000) @test only(Base.return_types(Base.promote_typeof, t)) == Type{Float64} @test only(Base.return_types(vcat, t)) == Vector{Float64} end + +# Infinite loop in inference on SSA assignment +const stop_infinite_loop::Base.Threads.Atomic{Bool} = Base.Threads.Atomic{Bool}(false) +function gen_infinite_loop_ssa_generator(world::UInt, source, _) + ci = make_codeinfo(Any[ + # Block 1 + (), + # Block 2 + PhiNode(Int32[1, 5], Any[SSAValue(1), SSAValue(3)]), + Expr(:call, tuple, SSAValue(2)), + Expr(:call, getindex, GlobalRef(@__MODULE__, :stop_infinite_loop)), + GotoIfNot(SSAValue(4), 2), + # Block 3 + ReturnNode(SSAValue(2)) + ]; slottypes=Any[Any]) + ci.slotnames = Symbol[:var"#self#"] + ci +end + +@eval function gen_infinite_loop_ssa() + $(Expr(:meta, :generated, gen_infinite_loop_ssa_generator)) + $(Expr(:meta, :generated_only)) + #= no body =# +end + +# We want to make sure that both this returns `Tuple` and that +# it doesn't infinite loop inside inference. +@test Core.Compiler.return_type(gen_infinite_loop_ssa, Tuple{}) === Tuple