-
-
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
inference: backward constraint propagation from call signatures #40880
inference: backward constraint propagation from call signatures #40880
Conversation
Fixes #37866? |
Oh, I didn't know there is already an issue on this. And yeah, this PR will fix that: julia> function find_first_above_5(v::Vector{Union{Nothing, Float64}})
for x in v
if x > 5.0
return x # x > 5.0 is MethodError for Nothing so can assume ::Float64
end
end
return 0.0
end
find_first_above_5 (generic function with 1 method)
julia> x = Union{Nothing, Float64}[1.0, 2.0, 3.0, 6.0, 4.0]
5-element Vector{Union{Nothing, Float64}}:
1.0
2.0
3.0
6.0
4.0
julia> find_first_above_5(x)
6.0
julia> Core.Compiler.return_types(find_first_above_5, Tuple{Vector{Union{Nothing, Float64}}})
1-element Vector{Any}:
Float64
julia> code_warntype(find_first_above_5, Tuple{Vector{Union{Nothing, Float64}}})
MethodInstance for find_first_above_5(::Vector{Union{Nothing, Float64}})
from find_first_above_5(v::Vector{Union{Nothing, Float64}}) in Main at REPL[1]:1
Arguments
#self#::Core.Const(find_first_above_5)
v::Vector{Union{Nothing, Float64}}
Locals
@_3::Union{Nothing, Tuple{Union{Nothing, Float64}, Int64}}
x::Union{Nothing, Float64}
Body::Float64
1 ─ %1 = v::Vector{Union{Nothing, Float64}}
│ (@_3 = Base.iterate(%1))
│ %3 = (@_3 === nothing)::Bool
│ %4 = Base.not_int(%3)::Bool
└── goto #6 if not %4
2 ┄ %6 = @_3::Tuple{Union{Nothing, Float64}, Int64}
│ (x = Core.getfield(%6, 1))
│ %8 = Core.getfield(%6, 2)::Int64
│ %9 = (x > 5.0)::Bool
└── goto #4 if not %9
3 ─ return x::Float64
4 ─ (@_3 = Base.iterate(%1, %8))
│ %13 = (@_3 === nothing)::Bool
│ %14 = Base.not_int(%13)::Bool
└── goto #6 if not %14
5 ─ goto #2
6 ┄ return 0.0 |
e87ad2b
to
34498f2
Compare
@nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @christopher-dG |
@nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @christopher-dG |
@vtjnash can I ask your review on this ? |
780e927
to
ae85281
Compare
Bump! |
83d28a2
to
34647a4
Compare
@nanosoldier |
Something went wrong when running your job:
Unfortunately, the logs could not be uploaded. |
I think @vtjnash has to manually upload the result. |
hm, does that mean a part of the system is kinda broken now ? |
Yes, the files now get too big to upload to github. JuliaCI/Nanosoldier.jl#97 |
Yeah, I'm not sure why the files suddenly changed from 20MB to 100MB |
Okay, thanks for uploading it anyway. |
Something went wrong when running your job:
Unfortunately, the logs could not be uploaded. |
34647a4
to
f9575da
Compare
A rebase would be fantastic! Should also fix #38274 |
Bump again! |
Separated from #40880. This subtle adjustment allows for more accurate type inference in the following kind of cases: ```julia function condition_object_update2(x) cond = x isa Int if cond # `cond` is known to be `Const(true)` within this branch return !cond ? nothing : x # ::Int else return cond ? nothing : 1 # ::Int end end @test Base.infer_return_type(condition_object_update2, (Any,)) == Int ```
This PR implements another (limited) backward analysis pass in abstract interpretation; it exploits signatures of matching methods and refines types of slots. Here are couple of examples where these changes will improve the accuracy: > generic function example ```julia addint(a::Int, b::Int) = a + b @test Base.infer_return_type((Any,Any,)) do a, b c = addint(a, b) return a, b, c # now the compiler understands `a::Int`, `b::Int` end == Tuple{Int,Int,Int} ``` > `typeassert` example ```julia @test Base.infer_return_type((Any,)) do a a::Int return a # now the compiler understands `a::Int` end == Int ``` Unlike `Conditional` constrained type propagation, this type refinement information isn't encoded within any lattice element, but rather they are propagated within the newly added field `frame.curr_stmt_change` of `frame::InferenceState`. For now this commit exploits refinement information available from call signatures of generic functions and `typeassert`.
@nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. |
Separated from #40880. This subtle adjustment allows for more accurate type inference in the following kind of cases: ```julia function condition_object_update2(x) cond = x isa Int if cond # `cond` is known to be `Const(true)` within this branch return !cond ? nothing : x # ::Int else return cond ? nothing : 1 # ::Int end end @test Base.infer_return_type(condition_object_update2, (Any,)) == Int ``` Also cleans up typelattice.jl a bit.
How come this is closed? Will there be a followup? I was hoping the linked issues will finally be fixed. |
I'm not sure. It might be because the base branch of this PR was the one I just merged a little while ago. I don't know how to reopen it, so I'll prepare a new PR. |
Now this PR is replaced by #55229. |
Separated from JuliaLang#40880. This subtle adjustment allows for more accurate type inference in the following kind of cases: ```julia function condition_object_update2(x) cond = x isa Int if cond # `cond` is known to be `Const(true)` within this branch return !cond ? nothing : x # ::Int else return cond ? nothing : 1 # ::Int end end @test Base.infer_return_type(condition_object_update2, (Any,)) == Int ``` Also cleans up typelattice.jl a bit.
This PR implements another (limited) backward analysis pass in abstract
interpretation; it exploits signatures of matching methods and refines
types of slots.
Here are couple of examples where these changes will improve the accuracy:
Unlike
Conditional
constrained type propagation, this type refinementinformation isn't encoded within any lattice element, but rather they
are propagated within the newly added field
frame.curr_stmt_change
offrame::InferenceState
.For now this commit exploits refinement information available from call
signatures of generic functions and
typeassert
.