Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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
[SYCL] Insert annotation in
annotated_ptr::get()
#12343[SYCL] Insert annotation in
annotated_ptr::get()
#12343Changes from 1 commit
e35dd53
efb363e
246b1ef
0457819
88fe720
3ebd695
dfbaad2
4b2b904
a0597c8
4b63406
File filter
Filter by extension
Conversations
Jump to
There are no files selected for viewing
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.
@Pennycook & @gmlueck : Currently the spec says "The raw pointer will not retain the annotations." Should this be changed to something like "It is implementation defined whether the raw pointer retains any annotations."?
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.
Do we precisely define anywhere what an "annotation" is?
I think it's important that
get()
returns a raw pointer that behaves exactly the same way as aT*
, and that any annotations that remain are not reflected in the type system. I'm not sure, but my guess is that because we say this returns aT*
, that must already be true?If you agree, I'm not opposed to saying that the raw pointer may retain some annotations. But if the user has no way of checking whether the annotations are there, or what an annotation even is, it seems like we could also achieve something similar by saying something vague like "Implementations are free to propagate information from properties of an
annotated_ptr
to the raw pointer." That may also be simpler than implementation-defined, because an implementation may not be able to succinctly describe all the situations in which the annotations will exist and continue to work.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 agree this needs to be clear. For me it is clear because it says it returns
T*
. Happy to make this clearer if you think it isn't clear.I'm OK with that too. Another option might be:
"An implementation can use the information of the properties for optimizations of access to the raw pointer."
Do we agree that if the user does an invalid access according to a property (e.g. deference an unaligned pointer with the alignment property), that this is UB even if the access is through the raw pointer obtained from
get()
? If so is this clear enough with either of those wordings? Or do we need to explicitly state that any UB access is still UB for the raw pointer obtained fromget
?For open-source compilers "implementation defined" often just means: the compiler code defines the behaviour :).
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 you think it's clear, I'm happy with it as is. I just wanted to make sure we were on the same page.
I'm okay with that too.
I don't think I agree with this, but I'm trying to think of exactly what this looks like in code.
I think the code above should not be UB. I think the implementation should be free to keep the annotations in place as an optimization, but only if doing so doesn't impact correctness.
I don't think that's inconsistent with the way things are defined, because in the example above a compiler would be smart enough to know that although
raw
is aligned,raw[1]
and the result ofraw++
are not. The implementation would be free to continue using aligned loads/stores for any access viaraw
that it can prove is aligned, but shouldn't assume alignment for all accesses.This is specific to alignment, of course. There might be cases where things really do end up being UB (like casting away a read-only or write-only property). I'm not sure how to bucket things or how to document that bucketing.
Brilliant! 🤣
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.
No. I agree that this isn't UB because the property doesn't apply after you modify it.
An example to show my concern:
This should be UB. I think the current wording isn't clear which line is UB. I think it would be good if the first two lines aren't UB. We have seen with nullptr being passed as kernel argument that users don't like if unused things are UB. And if assignment/
get
are UB in this example the example is UB even if the pointer is unused (with the 3rd line removed). But if we say that assignment andget
are never UB, than we should clarify that pointer access is UB even if done through the raw pointer.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.
To make this a bit more concrete: Should an implementation be allowed to put an assert for the property (e.g. alignment) in the constructor/assignment and/or
get
, or only be allowed to assert the property when used (e.g.operator*
)? Note that assert (which kills the program) is only allowed if an operation is UB.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, I see. Thanks for the example.
I agree that your example should be UB, and that it isn't clear from the specification exactly which part makes it UB.
I'd be okay with either:
Using the wording you proposed (i.e., any access via the annotated pointer is UB). The constructor and
get()
aren't UB.Using slightly stronger wording (e.g., calling any member function of the annotated pointer is UB). Then the constructor wouldn't be UB, but calling
get()
would be UB.One small advantage of 2. over 1. is that an implementation could use an
assert
as you suggested to throw an error. That's much easier than having to throw an error when the raw pointer is dereferenced.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 would strongly prefer we keep the first line UB:
This keeps the spec simple. We don't have to mention anything about propagating annotations; we merely have to define the property in such a way that it gives us information about the alignment of the pointer. The propagation is a legal optimization/use of the information we're given with no need to be documented. It's also an easy model to think about: only put the property on a pointer you know is aligned.
FYI, my interpretation is consistent with how the property is defined today in this extension: https://github.com/intel/llvm/blob/sycl/sycl/doc/extensions/experimental/sycl_ext_oneapi_kernel_arg_properties.asciidoc.
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 will annotate the pointer with all its properties, right? I don't think this is generally legal; this should be property dependent. For example, if a property was worded like this then you would not be allowed to apply it in this case:
"foo: the foo property directs the compiler to ensure that all accesses through this annotated_ptr should be done using foo loads or stores."
On the other hand, if it's worded like this (like alignment) then it is legal to apply it:
"foo: the foo property indicates that this pointer has foo characteristics."
The key difference is whether the property is information that the user is telling us about the pointer or whether it's a directive from the user for us to treat all dereferences of the pointer in a specific way.
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.
The code has been updated by adding a filter for the properties in
Props...
predicated on the type traitpropagateToPtrAnnotation
. Right now only two properties (buffer_location
andalignment
) are added to the whitelist.