-
-
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
Propagate constant calls to new! #28284
Conversation
Additionally, I request that we only merge this if it doesn't break Cassette. It could help Cassette IDK @jrevels? Anyways, I can't think of any other way to pass a constant value from the runtime to a generated function than to lift it to the type domain like this. |
This direction seems generally fine with me, but I'm not sure I like the try/catch too much. I wonder if we should have a version of jl_struct_v that signals its error rather than raising it. |
Yeah, @vtjnash and I couldn't really figure out which errors to rethrow. Any thoughts? |
flds = Any[ argtypes[i].val for i = 2:length(argtypes) ] | ||
try | ||
t = Const(ccall(:jl_new_structv, Any, (Any, Ptr{Cvoid}, UInt32), t, flds, length(flds))) | ||
catch ex |
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.
It would be better to check for the error conditions explicitly; it's faster than try/catch and would allow returning Bottom
for errors. I think all you need to check is that each value is of the corresponding field type. Elsewhere we assume that the number of arguments is correct.
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 believe that's correct. Plus it technically lets you do cool thinks like return a Const inferred value even if one of the values is only inferred as a union (as long as one of the union elements matches precisely - and they're both singletons at the moment).
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 was worried there might be another failure possibility (OOM? others?), but yeah, I guess it's just the type error, and we can check for that in the for-loop.
IIRC, the number of arguments is checked syntactically, so it would be invalid IR to discover otherwise.
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'm still a little new at this and I couldn't figure it out after looking around: anyone know which function would give the field types of the struct?
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.
fieldtype(type, index)
gives you the type of a field.
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.
Ah, yes, thanks! All fixed up, I think.
IIUC, it shouldn't break Cassette since Cassette intercepts |
end | ||
isconst &= ae isa Const | ||
isconst = isconst && (ae.val isa fieldtype(t, i - 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.
if !(ae.val isa fieldtype(t, i - 1)); t = Bottom; end
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.
Oh, also fieldtype(Bottom, i)
will 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.
Please add your test case, e.g. to test/core.jl
end | ||
isconst &= ae isa Const | ||
isconst = isconst && (ae.val isa fieldtype(t, i - 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.
Oh, also fieldtype(Bottom, i)
will error.
Inference test cases should go in test/compiler/compiler.jl. |
This might be a good implementation:
The idea is:
In fact it's possible we should break out as soon as we hit non-Const argument. |
all of this work is extremely cheap, but seeing |
So it looks like on windows ccall is having trouble passing a constant struct from a QuoteNode. We might be missing code to generate an address for a constant in that case. |
One of the appveyor tests fails. This makes me sad. The failing example is line 566 of test/ccall.c. I have created an MWE of the failing test case which should fail on appveyor on julia master: using InteractiveUtils
struct S
wild::Float32
wacky::Float32
waving::Float32
inflatable::Float64
armflailing::Float64
tubeman::Float64
end
f_julia(x::S) = x
f_c = @cfunction(f_julia, S, (S,))
eval(quote
function g()
return ccall(f_c, S, (S,), $(QuoteNode(S(42.0f0, 42.0f0, 42.0f0, 42.0, 42.0, 42.0))))
end
end)
println(g())
println(@code_typed(g()))
@code_llvm(g()) Executing the code on the master branch of julia produces:
Which is a real sad time because if you look at the line 10th to the bottom or so we have:
And there's something wrong with that null |
@0 is a reference to anonymous global variable #0. That’s mostly ok, but I think ccall expects that we are supposed to copy this to the stack (the mutation rules differ across the ccall boundary, which makes managing this interface a bit more special than normal codegen) |
9929fa0
to
426311c
Compare
As in #28335, I can no longer reproduce the failure on windows. Rebased, so I think this is good to go if the AppVeyor failure does not come back. |
Ping! Would be good to squash this a bit. |
I was just about to rebase this. We can squash this to one commit while merging. |
426311c
to
252a915
Compare
Looks like there was an httpbin outage while this was running, but the tests passed ok. Fine to squash merge from my perspective, but I'd like @JeffBezanson or @vtjnash to take a final look at the changes since they've sat around for a while. |
Please infer that calls to new with constant arguments are constant.
A MWE. Without this feature:
With this feature: