-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
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
Expr(:meta, :inline) sometimes ignored in @generated
#16712
Comments
Added a 0.5 milestone, since #16895 suggests that this causes a massive performance problem in some cases. (See also #16128 (comment).) |
@generated
@generated
I think I've got to the bottom of this: The compiler is emitting a Here's the evidence - I dumped the Expr(:block, # line 9,
Expr(:meta, :push_loc, :/home/cfoster/test_inference.jl)::Any, # line 10, #### Oh dear :-(
Expr(:meta, :inline)::Any, # line 11,
M.nothing, # line 12,
Expr(:inbounds, true)::Any,
SSAValue(0) = Expr(:call, Core.getfield, SlotNumber(id=2), :x)::Int64,
SSAValue(1) = Expr(:call, Core.getfield, SlotNumber(id=2), :y)::Int64,
Expr(:inbounds, :pop)::Any, # line 13,
Expr(:return, Expr(:new, M.Vec, SSAValue(0), SSAValue(1))::M.Vec)::Any
)::Any It's not yet clear to me what the right solution here is because http://docs.julialang.org/en/latest/devdocs/meta/ suggests that there should be one definitive meta block by design. I can hack around the problem by adding a few lines to
Side note: I think the mess with the |
I think we have to make metadata-consuming passes more flexible; we can't assume there will be only one meta node, or that meta nodes will occur in a certain order. So yes, I'd probably start by looking at leading statements until the first non-meta one. |
Ok, so if it seems right to modify the meta system, My current vague plan is to try updating the metadata handling so that it searches through all meta Exprs, but stops looking once it hits a non-meta statement (anything which is not an Perhaps a more consistent story would involve replacing the other kinds of adhoc metadata (inbounds, line numbers?) with |
Here's a bit of a survey. In base we appear to have: $ grep -h -R -o 'Expr( *:meta, *:[^,)]*' | sort | uniq
Expr(:meta, :doc
Expr(:meta, :inline
Expr(:meta, :noinline
Expr(:meta, :pop_loc
Expr(:meta, :pure
Expr(:meta, :push_loc
$ grep -R pushmeta
# after cleanup
pushmeta!(ex, :propagate_inbounds)
pushmeta!(ex, :polly) In the runtime, we have $ grep -R '`(meta' julia-syntax.scm
# after cleanup
`(meta ret-type ,R)
`(meta push_loc ,fname)
`(meta pop_loc)
$ grep -R meta_sym
# ... suggests
e->head == line_sym || e->head == meta_sym || e->head == inbounds_sym ||
e->head == boundscheck_sym || e->head == simdloop_sym To summarize List of current :meta constructsExpr(:meta, :doc Out of these, Meta-like constructs and possible translationExpr(:inbounds, true) It seems like we have two categories: those that apply to a julia function or block (doc, inline, noinline, pure, propagate_inbounds, polly, simdloop) and those that apply to a "meta block" which are pushed and popped to avoid introducing an actual block into the ast (push_loc, pop_loc, inbounds, boundscheck). It would be nice to have a systematic way to deal with the second class within the There's also the |
Yes, it would be good to make it uniform and use We can't introduce blocks in the IR; it only supports a single array of statements. Yes, LineNumberNode is a special case because there are so many. |
Also, I might have been wrong about it being ok to search until the first non-meta node. To be safe we should probably keep searching all statements. |
@c42f, are you going to put up a PR for this? |
Well, making a PR seems like a good way to continue procrastinating instead of writing my juliacon talk ;-) I'm happy to have a crack at this, but if someone else wants to claim it in the interests of just getting it fixed, that's also totally ok by me. Perhaps I should fix the immediate problem by just making |
Yes, let's do the narrow fix, since it's getting to 0.5 crunch time. |
- detect pure and inline meta once, in the front end - fixes #16712 - remove `skip_meta` since it probably assumes too much about where meta nodes occur - add jl_ prefix to has_meta - remove location/pure/inline meta early, in the front end (the first line node isn't needed, since this info is in the Method object) - remove null_sym; this Expr head doesn't occur in the IR
- detect pure and inline meta once, in the front end - fixes #16712 - remove `skip_meta` since it probably assumes too much about where meta nodes occur - add jl_ prefix to has_meta - remove location/pure/inline meta early, in the front end (the first line node isn't needed, since this info is in the Method object) - remove null_sym; this Expr head doesn't occur in the IR
With the push_loc mechanism for source file tracking, it's now common to have more than one meta expression per function body, at least in generated functions. This means that popmeta! needs to search further than the first meta expression to avoid ignoring metadata, including inline annotations. Fixes #16712.
- detect pure and inline meta once, in the front end - fixes #16712 - remove `skip_meta` since it probably assumes too much about where meta nodes occur - add jl_ prefix to has_meta - remove location/pure/inline meta early, in the front end (the first line node isn't needed, since this info is in the Method object) - remove null_sym; this Expr head doesn't occur in the IR
- detect pure and inline meta once, in the front end - fixes #16712 - remove `skip_meta` since it probably assumes too much about where meta nodes occur - add jl_ prefix to has_meta - remove location/pure/inline meta early, in the front end (the first line node isn't needed, since this info is in the Method object) - remove null_sym; this Expr head doesn't occur in the IR
- detect pure and inline meta once, in the front end - fixes #16712 - remove `skip_meta` since it probably assumes too much about where meta nodes occur - add jl_ prefix to has_meta - remove location/pure/inline meta early, in the front end (the first line node isn't needed, since this info is in the Method object) - remove null_sym; this Expr head doesn't occur in the IR
- detect pure and inline meta once, in the front end - fixes JuliaLang#16712 - remove `skip_meta` since it probably assumes too much about where meta nodes occur - add jl_ prefix to has_meta - remove location/pure/inline meta early, in the front end (the first line node isn't needed, since this info is in the Method object) - remove null_sym; this Expr head doesn't occur in the IR
- detect pure and inline meta once, in the front end - fixes #16712 - remove `skip_meta` since it probably assumes too much about where meta nodes occur - add jl_ prefix to has_meta - remove location/pure/inline meta early, in the front end (the first line node isn't needed, since this info is in the Method object) - remove null_sym; this Expr head doesn't occur in the IR
While improving type inference in FixedSizeArrays, I've found that
Expr(:meta, :inline)
is sometimes ignored inside@generated
functions in 0.5. Here's a somewhat minimal test case:For (A), the
nothing
may be replaced with various other things and the problem still occurs (for example, types egInt
), though some values like the empty tuple or a literal integer don't cause an issue.I'm not quite sure whether the compiler is always meant to believe the inline metadata.
The text was updated successfully, but these errors were encountered: