-
-
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 for splatting numbers (and more) #27434
Conversation
Same error across the board:
This is interesting, because a) it somehow managed to build locally and b) even if inference gives a wrong result, bad things may happen, but invalid LLVM IR should not be among them AFAICT. |
Ok, a) resolved: diff --git a/base/number.jl b/base/number.jl
index 89cec5169e..514747bed3 100644
--- a/base/number.jl
+++ b/base/number.jl
@@ -233,7 +233,8 @@ julia> widemul(Float32(3.), 4.)
"""
widemul(x::Number, y::Number) = widen(x)*widen(y)
-iterate(x::Number, done = false) = done ? nothing : (x, true)
+iterate(x::Number) = (x, true)
+iterate(x::Number, ::Any) = nothing
isempty(x::Number) = false
in(x::Number, y::Number) = x == y
is enough to make |
Can anyone give me a clue how I can figure out what method is being compiled when that error is thrown? |
if !isa(nounion, DataType) || !(nounion <: Tuple) || isvatuple(nounion) || length(nounion.parameters) != 2 | ||
return Vararg{Any} | ||
valtype = Any | ||
break | ||
end | ||
if nounion.parameters[1] <: valtype && nounion.parameters[2] <: statetype |
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.
Copy this conditional above? (or at least the nounion.parameters[2] <: statetype
part of it). If the new statetype
is narrower, this must have been an infinite iterator (or throws an error).
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.
True. However, for an infinite iterator, we get a slightly wider type then, e.g. Tuple{Char,Vararg{Char,N} where N}
instead of Body::Tuple{Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Char,Vararg{Char,N} where N}
for splatting Iterators.repeated('a')
. Probably doesn't matter. Or is your suggestion to return Any[Bottom}
(instead of break
ing out of the loop) then? While theoretically correct (or did I get something wrong?), that looks rather aggressive.
base/number.jl
Outdated
@@ -233,7 +233,8 @@ julia> widemul(Float32(3.), 4.) | |||
""" | |||
widemul(x::Number, y::Number) = widen(x)*widen(y) | |||
|
|||
iterate(x::Number, done = false) = done ? nothing : (x, true) | |||
iterate(x::Number) = (x, true) |
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.
Should never matter (after inference, inlining, or SROA), but constructing (x, nothing)
would require 1 byte less space. Maybe use that instead?
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.
Yes. I've actually changed that locally to see whether it makes a difference with the failure in make julia-debug
(which it doesn't), and realized that it might be better anyway.
@@ -372,37 +372,54 @@ function precise_container_type(@nospecialize(arg), @nospecialize(typ), vtypes:: | |||
elseif tti0 <: Array | |||
return Any[Vararg{eltype(tti0)}] | |||
else | |||
return Any[abstract_iteration(typ, vtypes, sv)] | |||
return abstract_iteration(typ, vtypes, sv) | |||
end | |||
end | |||
|
|||
# simulate iteration protocol on container type up to fixpoint | |||
function abstract_iteration(@nospecialize(itertype), vtypes::VarTable, sv::InferenceState) | |||
tm = _topmod(sv) |
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.
As implemented right now, this actually always uses Base
, not _topmod(sv)
to find iterate
. We should probably redefine this as if isdefined(Main, :Base) || !isdefined(Main.Base, :iterate) || !isconst(Main.Base, :iterate)
to be pedantic and precise about correctness here
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.
Ok, will adjust then.
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.
Um, are you sure? If I look at e.g. Core.Compiler.append_any(1)
, it seems to be calling Core.Compiler.iterate
. And that's what we want to reflect, no?
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 don’t think there’s any callers of Core.Compiler.append_any
. The implementation of _apply right now always uses Base
Ok, I've incorporated the comments locally (including returning Bottom for infinite iterators), but I'm struggling with the invalid LLVM IR when doing
with this debug info (excerpt):
How do I figure out for which types this was specialized exactly? |
a69650f
to
df14e50
Compare
Ok, with #27609 in, this now seems to pass CI (Circle 64bit was killed (OOM?), Travis on OSX was hit by #26725). I've also addressed Jameson's remarks, so unless @nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan |
Exploit the fact that the (minimum) number of elements obtained from iteration can be derived from the types in certain cases and hence, a more exact type can be inferred for splatting them.
Letting the presence of a second argument alone decide whether iteration is done lets `abstract_iteration` determine that splatting a `Number` yields exactly one `Number`.
df14e50
to
e086018
Compare
As I let this go a bit stale, @nanosoldier |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. cc @ararslan |
The logical next step would be eliding the call to julia/base/compiler/ssair/inlining.jl Lines 793 to 794 in 2e168b5
iterate calls in julia/base/compiler/ssair/inlining.jl Line 556 in 2e168b5
But I'm relatively clueless how to thread the information gathered during inference through to the inlining pass. If @Keno or @vtjnash can give me a hint, I might try to give it a shot. |
Fixes #22291, closes #22292 (from where I've taken the tests).
But even more: