-
-
Notifications
You must be signed in to change notification settings - Fork 5.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Unnecessary GC frame? #49823
Comments
The issue with this is that the operations on the tuple aren't inferred |
It's a loop over a tuple of length |
No we don't. But it doesn't know that 😆 . In fact it should probably be fully unrolled. |
function in(x, itr)
anymissing = false
for y in itr
v = (y == x)
if ismissing(v)
anymissing = true
elseif v
return true
end
end
return anymissing ? missing : false
end I guess because we don't do any loop analysis in the Julia compiler? Now, we don't have to be able to unroll it, or even infer 2, but would be nice to figure out under more general situations that loops like this are going to terminate eventually. Body::Bool (+c,+e,!n,!t,+s,+m,+i)
1 ── nothing
2 ── goto #3
3 ── nothing
4 ── %4 = Base.getfield(itr, 1, true)::Int64
└─── goto #5
5 ── goto #6
6 ── nothing
7 ┄─ %8 = φ (#6 => %4, #17 => %24)::Int64
│ %9 = φ (#6 => 2, #17 => %25)::Int64
└─── %10 = (%8 === x)::Bool
8 ── goto #10 if not %10
9 ── return true
10 ─ %13 = Base.sle_int(1, %9)::Bool
└─── goto #12 if not %13
11 ─ %15 = Base.sle_int(%9, 2)::Bool
└─── goto #13
12 ─ nothing
13 ┄ %18 = φ (#11 => %15, #12 => false)::Bool
└─── goto #15 if not %18
14 ─ %20 = Base.getfield(itr, %9, true)::Int64
│ %21 = Base.add_int(%9, 1)::Int64
└─── goto #16
15 ─ goto #16
16 ┄ %24 = φ (#14 => %20)::Int64
│ %25 = φ (#14 => %21)::Int64
│ %26 = φ (#14 => false, #15 => true)::Bool
│ %27 = Base.not_int(%26)::Bool
└─── goto #18 if not %27
17 ─ goto #7
18 ─ nothing
19 ─ return false I don't see anything that looks like it can throw here. |
Iterate can throw |
Where/how? |
Well, before optimization, I'm not super sure where it goes wrong here. |
I don't think that adding effect annotations to It looks like we can eliminate the allocation if we inline the julia> evtest = @NamedTuple{evid::Int8, base_time::Float64}[(evid = 1, base_time = 0.0), (evid = -1, base_time = 0.0)];
julia> fl1(t, events) = @inline findlast(x -> x.evid ∈ (1, 4) && x.base_time <= t, events)
fl1 (generic function with 1 method)
julia> @btime fl1(0.0, $evtest)
4.208 ns (0 allocations: 0 bytes)
1
julia> fl3(t, events) = @inline findlast(x -> any(==(x.evid), (1,4)) && x.base_time <= t, events)
fl3 (generic function with 1 method)
julia> @btime fl3(0.0, $evtest)
4.209 ns (0 allocations: 0 bytes)
1
julia> fl5(t, events) = begin
f = let t=t
x -> x.evid ∈ (1, 4) && x.base_time <= t
end
@inline findlast(f, events)
end
fl5 (generic function with 1 method)
julia> @btime fl5(0.0, $evtest)
4.208 ns (0 allocations: 0 bytes)
1 |
I agree, the weird thing is that they aren't arrays but tuples, which get inferred as constant by the compiler, but it doesn't try to do too much with that information at the effect level. |
We need specialized implementations for tuples with |
I have a very hard time telling these codes apart with Cthulhu.
We can optimize
in
forTuple
s as one workaround, but I think the compiler should be able to handle this well.The text was updated successfully, but these errors were encountered: