-
-
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
Make Expr(:invoke) target be a CodeInstance, not MethodInstance #54899
Conversation
af03fd5
to
91be20b
Compare
ce5726f
to
d2c2e51
Compare
2f824bf
to
33701f1
Compare
33701f1
to
4525784
Compare
a9c4eeb
to
fe8d042
Compare
a5a2db9
to
6f64fd6
Compare
52efd2b
to
2ecae72
Compare
140f560
to
23c3250
Compare
d33a71e
to
809d3fb
Compare
2317380
to
a7c8401
Compare
128e4f2
to
16c53a7
Compare
base/compiler/ssair/inlining.jl
Outdated
@@ -1539,8 +1549,6 @@ function handle_modifyop!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyOp | |||
edge = info.edges[1] |
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.
@aviatesk is this the right API calls to use to extract the CodeInstance for a result? It is now the only place we call compileable_specialization
with a MethodInstance instead of a CodeInstance, so it would be nice to get to simplify this callsite too
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.
There isn’t an API to extract a specific edge from CallInfo
, we only have add_edges!
. As for handle_modify_op!
, some checks are performed beforehand to ensure this code works correctly.
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.
In cases where edge === nothing
, it’s usually because inference failed on the inner operations of the modify-function, so it might be fine to simply reject those.
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.
okay, I thought other parts were using getresult
, so I wasn't sure if that applied here
16c53a7
to
b10df4b
Compare
Together with #54899, this PR is intending to replicate the functionality of #54373, which allowed particular specializations to have a different ABI signature than what would be suggested by the MethodInstance's `specTypes` field. This PR handles that by adding a special `ABIOverwrite` type, which, when placed in the `owner` field of a `CodeInstance` instructs the system to use the given signature instead.
Together with #54899, this PR is intending to replicate the functionality of #54373, which allowed particular specializations to have a different ABI signature than what would be suggested by the MethodInstance's `specTypes` field. This PR handles that by adding a special `ABIOverwrite` type, which, when placed in the `owner` field of a `CodeInstance` instructs the system to use the given signature instead.
@@ -1042,6 +1042,7 @@ call obsolete versions of a function `f`. | |||
Prior to Julia 1.9, this function was not exported, and was called as `Base.invokelatest`. | |||
""" | |||
function invokelatest(@nospecialize(f), @nospecialize args...; kwargs...) | |||
@inline |
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.
Any reason for adding this?
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.
Just noticing that codegen was doing dumb stuff here because of the nospecialize. It would generate a call to make a Tuple for the args so that it could call the apply function to unpack those again to call the builtin 🙄
base/compiler/ssair/inlining.jl
Outdated
@@ -1539,8 +1549,6 @@ function handle_modifyop!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyOp | |||
edge = info.edges[1] |
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.
There isn’t an API to extract a specific edge from CallInfo
, we only have add_edges!
. As for handle_modify_op!
, some checks are performed beforehand to ensure this code works correctly.
base/compiler/ssair/inlining.jl
Outdated
@@ -1539,8 +1549,6 @@ function handle_modifyop!_call!(ir::IRCode, idx::Int, stmt::Expr, info::ModifyOp | |||
edge = info.edges[1] |
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.
In cases where edge === nothing
, it’s usually because inference failed on the inner operations of the modify-function, so it might be fine to simply reject those.
There is this another place where julia/Compiler/src/ssair/inlining.jl Line 869 in b10df4b
I recall that most of these cases were due to inference failures, but simply doing |
I tried that and confirmed: it especially regresses the case where we found there was a get_compileable_sig different from sig, and that it was therefore wasteful to infer the sig, but in that case we still want to call compileable_specialization to find the get_compileable_sig target and use that as the invoke target. I updated the comment here to mention this. |
94762b7
to
a7545af
Compare
assert(jl_is_method_instance(meth)); | ||
jl_value_t *c = args[0]; | ||
assert(jl_is_code_instance(c) || jl_is_method_instance(c)); | ||
jl_method_instance_t *meth = jl_is_method_instance(c) ? (jl_method_instance_t*)c : ((jl_code_instance_t*)c)->def; |
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.
This should probably just invoke the codeinstance directly.
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.
Perhaps. We still have to support the legacy thing for a bit longer, at least while we solve a few last inference / optimizer bugs around this
a7545af
to
692a21b
Compare
One stacked PR remaining (#56598), but this is already passing tests, so it can be merged once that is done |
692a21b
to
f89d58d
Compare
This should be ready to go now, since it seems working, it would be nice to merge before it picks up spurious conflicts. @nanosoldier Some improvements can be done later:
|
Make :invoke edges to CodeInstance (with rettype and edges) instead of MethodInstance, for more accuracy (except when inference made a mistake). Remove lookup parameter from codegen, since we no longer do any lookup.
f89d58d
to
cf3e3e3
Compare
@vtjnash small conflicts with my worldage PR, so I rebased this for you, just FYI |
Your benchmark job has completed - possible performance regressions were detected. A full report can be found here. |
Although these code paths don’t seem to be used very often.
This PR allows generated functions to return a `CodeInstance` containing optimized IR, allowing them to bypass inference and directly adding inferred code into the ordinary course of execution. This is an enabling capability for various external compiler implementations that may want to provide compilation results to the Julia runtime. As a minimal demonstrator of this capability, this adds a Cassette-like `with_new_compiler` higher-order function, which will compile/execute its arguments with the currently loaded `Compiler` package. Unlike `@activate Compiler[:codegen]`, this change is not global and the cache is fully partitioned. This by itself is a very useful feature when developing Compiler code to be able to test the full end-to-end codegen behavior before the changes are capable of fully self-hosting. A key enabler for this was the recent merging of #54899. This PR includes a hacky version of the second TODO left at the end of that PR, just to make everthing work end-to-end. This PR is working end-to-end, but all three parts of it (the CodeInstance return from generated functions, the `with_new_compiler` feature, and the interpreter integration) need some additional cleanup. This PR is mostly intended as a discussion point for what that additional work needs to be.
This is a look at what is necessary and what it would look like for codegen to be using CodeInstance directly to get the API for a function call (specifically the rettype), rather than using a lookup call at that point to decide upon the API. It is based around the idea that eventually we would keep track of these anyways to form a graph of the inferred edge data, for use later in validation anyways (instead of attempting to invert the backedges graph in staticdata_utils.c), so we might as well use the same target type for the :invoke call representation also.
This does not depend upon #54894, but is much better with it. It did depend upon #54738, thoughthere still remains work to do to teach it how to select a correct alternative CodeInstance after deserializing. Also still to do: codegen also should be looking for equivalent objects, not just using the exact one given, per the definition of equivalency in https://hackmd.io/@vtjnash/codeinstances (and that is what precompile should be doing also).Depends on
#56552,#56551,#56547,#56598