-
-
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: refine slot undef info within then
branch of @isdefined
#55545
Conversation
aa8194c
to
8483130
Compare
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. |
# `isdefined` indicates this `Conditional` is from `@isdefined slot`, implying that | ||
# the `undef` information of `slot` can be improved in the then branch. | ||
# Since this is only beneficial for local inference, it is not translated into `InterConditional`. | ||
isdefined::Bool |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure this works conceptually. isdefined
-ness is not a flow property and can be reset by NewvarNode
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Basically to optimize isdefined you need to do ssa construction
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought that is a data-flow property. My understanding was that the type/isdefined-ness information for a slot gets reset by NewvarNode
, but then both of those get updated along with the abstract interpretation. E.g. within smerge
, both typ
and undef
are being merged.
The purpose of this PR was to eliminate unnecessary :throw_undef_if_not
during SSA construction, but I might be making a fundamental mistake.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Turns out Conditional
itself is just broken: #55548
8483130
to
5e7f92d
Compare
@nanosoldier |
If the issue is related to |
The package evaluation job you requested has completed - possible new issues were detected. |
5e7f92d
to
0fcbc16
Compare
@nanosoldier |
0fcbc16
to
db19d0a
Compare
The package evaluation job you requested has completed - possible new issues were detected. |
By adding some information to `Conditional`, it is possible to improve the `undef` information of `slot` within the `then` branch of `@isdefined slot`. As a result, it's now possible to prove the `:nothrow`-ness in cases like: ```julia @test Base.infer_effects((Bool,Int)) do c, x local val if c val = x end if @isdefined val return val end return zero(Int) end |> Core.Compiler.is_nothrow ```
db19d0a
to
3b9dc4b
Compare
pkgeval looks just fine, so I believe this PR should be fine to proceed as is, while any issues related to |
As an application of #55545, this commit avoids the insertion of `:throw_undef_if_not` nodes when the defined-ness of a slot is guaranteed by abstract interpretation. ```julia julia> function isdefined_nothrow(c, x) local val if c val = x end if @isdefined val return val end return zero(Int) end; julia> @code_typed isdefined_nothrow(true, 42) ``` ```diff diff --git a/old b/new index c4980a5c9c..3d1d6d30f0 100644 --- a/old +++ b/new @@ -4,7 +4,6 @@ CodeInfo( 3 ┄ %3 = φ (#2 => x, #1 => #undef)::Int64 │ %4 = φ (#2 => true, #1 => false)::Bool └── goto #5 if not %4 -4 ─ $(Expr(:throw_undef_if_not, :val, :(%4)))::Any -└── return %3 +4 ─ return %3 5 ─ return 0 ) => Int64 ```
JuliaLang#55545) By adding some information to `Conditional`, it is possible to improve the `undef` information of `slot` within the `then` branch of `@isdefined slot`. As a result, it's now possible to prove the `:nothrow`-ness in cases like: ```julia @test Base.infer_effects((Bool,Int)) do c, x local val if c val = x end if @isdefined val return val end return zero(Int) end |> Core.Compiler.is_nothrow ```
As an application of #55545, this commit avoids the insertion of `:throw_undef_if_not` nodes when the defined-ness of a slot is guaranteed by abstract interpretation. ```julia julia> function isdefined_nothrow(c, x) local val if c val = x end if @isdefined val return val end return zero(Int) end; julia> @code_typed isdefined_nothrow(true, 42) ``` ```diff diff --git a/old b/new index c4980a5c9c..3d1d6d30f0 100644 --- a/old +++ b/new @@ -4,7 +4,6 @@ CodeInfo( 3 ┄ %3 = φ (#2 => x, #1 => #undef)::Int64 │ %4 = φ (#2 => true, #1 => false)::Bool └── goto #5 if not %4 -4 ─ $(Expr(:throw_undef_if_not, :val, :(%4)))::Any -└── return %3 +4 ─ return %3 5 ─ return 0 ) => Int64 ```
#55545) By adding some information to `Conditional`, it is possible to improve the `undef` information of `slot` within the `then` branch of `@isdefined slot`. As a result, it's now possible to prove the `:nothrow`-ness in cases like: ```julia @test Base.infer_effects((Bool,Int)) do c, x local val if c val = x end if @isdefined val return val end return zero(Int) end |> Core.Compiler.is_nothrow ```
As an application of #55545, this commit avoids the insertion of `:throw_undef_if_not` nodes when the defined-ness of a slot is guaranteed by abstract interpretation. ```julia julia> function isdefined_nothrow(c, x) local val if c val = x end if @isdefined val return val end return zero(Int) end; julia> @code_typed isdefined_nothrow(true, 42) ``` ```diff diff --git a/old b/new index c4980a5c9c..3d1d6d30f0 100644 --- a/old +++ b/new @@ -4,7 +4,6 @@ CodeInfo( 3 ┄ %3 = φ (#2 => x, #1 => #undef)::Int64 │ %4 = φ (#2 => true, #1 => false)::Bool └── goto #5 if not %4 -4 ─ $(Expr(:throw_undef_if_not, :val, :(%4)))::Any -└── return %3 +4 ─ return %3 5 ─ return 0 ) => Int64 ```
By adding some information to
Conditional
, it is possible to improve theundef
information ofslot
within thethen
branch of@isdefined slot
.As a result, it's now possible to prove the
:nothrow
-ness in cases like:@nanosoldier
runbenchmarks("inference", vs=":master")