-
-
Notifications
You must be signed in to change notification settings - Fork 5.7k
Closed
Labels
compiler:inferenceType inferenceType inference
Description
This snippet
@noinline function step(acc, x)
xs, = acc
y = x > 0.0 ? x : missing
if y isa eltype(xs)
ys = push!(xs, y)
else
ys = vcat(xs, [y])
end
return (ys,)
end
@noinline function _foldl_iter(rf, val::T, iter, state) where {T}
while true
ret = iterate(iter, state)
ret === nothing && break
x, state = ret
y = rf(val, x)
if y isa T
val = y
else
return _foldl_iter(rf, y, iter, state)
end
end
return val
end
@code_typed optimize=false _foldl_iter(step, (Missing[],), [0.0], 1)prints
CodeInfo(
1 ─ $(Expr(:meta, :noinline))
│ (val@_10 = val@_3)::Tuple{Array{Missing,1}}
└── (state@_11 = state@_5)::Int64
2 ┄ goto #9 if not true
3 ─ Core.NewvarNode(:(x))::Any
│ Core.NewvarNode(:(@_8))::Any
│ Core.NewvarNode(:(y))::Any
│ (ret = Main.iterate(iter, state@_11))::Union{Nothing, Tuple{Float64,Int64}}
│ %9 = (ret === Main.nothing)::Bool
└── goto #5 if not %9
4 ─ goto #9
5 ─ %12 = Base.indexed_iterate(ret::Tuple{Float64,Int64}, 1)::Core.Compiler.PartialStruct(Tuple{Float64,Int64}, Any[Float64, Core.Compiler.Const(2, false)])
│ (x = Core.getfield(%12, 1))::Float64
│ (@_8 = Core.getfield(%12, 2))::Core.Compiler.Const(2, false)
│ %15 = Base.indexed_iterate(ret::Tuple{Float64,Int64}, 2, @_8::Core.Compiler.Const(2, false))::Core.Compiler.PartialStruct(Tuple{Int64,Int64}, Any[Int64, Core.Compiler.Const(3, false)])
│ (state@_11 = Core.getfield(%15, 1))::Int64
│ (y = (rf)(val@_10, x))::Tuple{Union{Array{Missing,1}, Array{Union{Missing, Float64},1}}}
│ %18 = (y isa $(Expr(:static_parameter, 1)))::Bool
└── goto #7 if not %18
6 ─ (val@_10 = y::Tuple{Array{Missing,1}})::Tuple{Array{Missing,1}}
└── goto #8
7 ─ %22 = Main._foldl_iter(rf, y, iter, state@_11)::Tuple{Union{Array{Missing,1}, Array{Union{Missing, Float64},1}}}
└── return %22
8 ─ goto #2
9 ┄ return val@_10
) => Tuple{Union{Array{Missing,1}, Array{Union{Missing, Float64},1}}}I expect %22 = Main._foldl_iter(rf, y, iter, state@_11)::Tuple{Array{Union{Missing, Float64},1}} instead of %22 = Main._foldl_iter(rf, y, iter, state@_11)::Tuple{Union{Array{Missing,1}, Array{Union{Missing, Float64},1}}} which has a tuple-of-union. This seems to be due that the argument y in #7 is inferred to be Tuple{Union{Array{Missing,1}, Array{Union{Missing, Float64},1}}}. (Indeed, this is what @descend shows me. Also, I see a corresponding @jl_apply_generic in the LLVM IR. IIUC this is a sign of a dynamic dispatch.)
The type is narrowed as expected if I tweak the example to avoid using intermediate tuple:
@noinline function step2(xs, x)
y = x > 0.0 ? x : missing
if y isa eltype(xs)
ys = push!(xs, y)
else
ys = vcat(xs, [y])
end
return ys
end
@code_typed optimize=false _foldl_iter(step2, Missing[], [0.0], 1)prints
...
7 ─ %22 = Main._foldl_iter(rf, y::Array{Union{Missing, Float64},1}, iter, state@_11)::Array{Union{Missing, Float64},1}
...It'd be great if this works in the first example too.
Checked with Julia 1.5.0-DEV.630.
Metadata
Metadata
Assignees
Labels
compiler:inferenceType inferenceType inference