-
-
Notifications
You must be signed in to change notification settings - Fork 5.4k
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
RFC: specialized calling convention for pure functions that return a constant #16837
Conversation
Hi Jeff, Just a general question as to the design of constant propagation and where this is going - are you planning on allowing constant propagation and inlining during inference, here, or just afterwards? I see the post-inference optimizations are very useful, but sometimes these calculations affect type. For instance, a simple example that I would love to see be inferrable: addval{M,N}(::Type{Val{M}}, ::Type{Val{N}}) = Val{M+N} If this constant is inlined post-inference, then can its type parameter be used for later calculations? e.g. function foo()
a = Val{2}
b = Val{3}
c = Val{4}
d = addval(a,b)
return addval(d,c)
end (Where I really want to end up with is: @inline Base.getindex{Idx}(table::Table{Idx}, field::Symbol) = Table.data[find_index(Idx, field)] where |
This change is actually orthogonal to inference and constant propagation. It just says that if we can infer the result of a pure function to be a constant, then we don't need to generate native code for it or keep its IR around. Separately, we do hope to improve constant propagation over time. I think |
8282c95
to
f2b6b51
Compare
OK, thanks, I get it now - this is an internal optimization for things like pure functions that only depend on the types of their inputs.
Cool, I'm really looking forward to this. :)
Yes, I realize it is difficult (expensive, rather) to analyze based on value. I was more saying that if my |
f2b6b51
to
49f9020
Compare
@@ -1916,11 +1924,36 @@ function finish(me::InferenceState) | |||
end | |||
widen_all_consts!(me.linfo) | |||
|
|||
if (isa(me.bestguess,Const) && me.bestguess.val !== nothing) || | |||
(isType(me.bestguess) && !has_typevars(me.bestguess.parameters[1],true)) | |||
if !ispure && length(me.linfo.code) < 10 |
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.
is 10 just an arbitrarily chosen cutoff for this?
return true | ||
end | ||
if e.head === :static_parameter | ||
if head === :static_parameter || head === :meta || head === :line || head === :gotoifnot || | ||
head === :inbounds || head === :boundscheck |
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.
:gotoifnot
isn't effect-free
49f9020
to
a632ed9
Compare
Fixed. |
a632ed9
to
488ecb4
Compare
LabelNode too? |
488ecb4
to
e0c12b5
Compare
7dae55d
to
62fe058
Compare
lgtm. just needs a rebase |
this allows deleting their code and avoiding native code gen entirely
62fe058
to
76fcfde
Compare
This allows deleting their code and avoiding native code gen entirely. This happens a fair amount due to functions like
promote_type
,zero
, trait functions, etc. It's about 8% of all inferred functions in the system image. However since such functions tend to be very small, the gains are not as much as that number might imply.