-
Notifications
You must be signed in to change notification settings - Fork 787
[SYCL][Doc] Adjust design for compile-time properties through add_ir_annotations_member #5884
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
Changes from all commits
21baacb
9abc31a
c941c6e
eaf9d55
a4ab8f7
5d081c8
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -465,25 +465,50 @@ When the device compiler generates code to reference the decorated member | |
variable, it emits a call to the LLVM intrinsic function | ||
[`@llvm.ptr.annotation`][10] that annotates the pointer to that member | ||
variables, similar to the way the existing `[[clang::annotate()]]` attribute | ||
works. Illustrating this with some simplified LLVM IR that matches the example | ||
code above: | ||
works. | ||
|
||
[10]: <https://llvm.org/docs/LangRef.html#llvm-ptr-annotation-intrinsic> | ||
|
||
The front-end encodes the properties from the C++ attribute | ||
`[[__sycl_detail__::add_ir_annotations_member()]]` into the | ||
`@llvm.ptr.annotation` call as follows: | ||
|
||
* The first parameter to `@llvm.ptr.annotation` is the pointer to annotate (as | ||
with any call to this intrinsic). | ||
* The second parameter is the literal string `"sycl-properties"`. | ||
* The third parameter is the name of the source file (as with any call to this | ||
intrinsic). | ||
* The fourth parameter is the line number (as with any call to this intrinsic). | ||
* The fifth parameter is a pointer to a constant global variable. The type of | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it allowed adding parameters to the There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That is curious. According to the intrinsic definition in Intrinsics.td it has 5 parameters, the last being another |
||
this variable is an anonymous structure. The first field of the structure is | ||
a pointer to a string literal representing the name of the first property. The | ||
second field of the structure is a pointer to a string literal representing | ||
the value of the first property. The third field of the structure is a pointer | ||
to a string literal representing the name of the second property, etc. | ||
Since each property has exactly one value, this tuple has an even number of | ||
elements. Pointers to property value strings may be a null-pointer, signalling | ||
a property without a value. | ||
|
||
The resulting LLVM IR for the previous example would be: | ||
gmlueck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
``` | ||
@.str = private unnamed_addr constant [16 x i8] c"sycl-properties\00", | ||
section "llvm.metadata" | ||
@.str.1 = private unnamed_addr constant [9 x i8] c"file.cpp\00", | ||
section "llvm.metadata" | ||
@.str.2 = private unnamed_addr constant [9 x i8] c"sycl-foo\00", align 1 | ||
@.str.3 = private unnamed_addr constant [9 x i8] c"sycl-bar\00", align 1 | ||
@.str.2 = private unnamed_addr constant [9 x i8] c"sycl-foo\00", | ||
section "llvm.metadata" | ||
@.str.3 = private unnamed_addr constant [9 x i8] c"sycl-bar\00", | ||
section "llvm.metadata" | ||
@.str.4 = private unnamed_addr constant [3 x i8] c"32\00", | ||
section "llvm.metadata" | ||
|
||
@.args = private unnamed_addr constant { [9 x i8]*, i8*, [9 x i8]*, i32 } | ||
@.args = private unnamed_addr constant { [9 x i8]*, i8*, [9 x i8]*, [3 x i8]* } | ||
{ | ||
[9 x i8]* @.str.2, ; Name of first property "sycl-foo" | ||
i8* null, ; Null indicates this property has no value | ||
[9 x i8]* @.str.3, ; Name of second property "sycl-bar" | ||
i32 32 ; Value of second property | ||
[3 x i8]* @.str.4 ; Value of second property | ||
}, | ||
section "llvm.metadata" | ||
|
||
|
@@ -497,31 +522,14 @@ define void @foo(i32* %ptr) { | |
i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0), | ||
i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i64 0, i64 0), | ||
i32 3, | ||
i8* bitcast ({ [9 x i8]*, i8*, [9 x i8]*, i32 }* @.args to i8*)) | ||
i8* bitcast ({ [9 x i8]*, i8*, [9 x i8]*, [3 x i8]* }* @.args to i8*)) | ||
|
||
%3 = bitcast i8* %2 to i32** | ||
store i32* %ptr, i32** %3 | ||
ret void | ||
} | ||
``` | ||
|
||
The front-end encodes the properties from the C++ attribute | ||
`[[__sycl_detail__::add_ir_annotations_member()]]` into the | ||
`@llvm.ptr.annotation` call as follows: | ||
|
||
* The first parameter to `@llvm.ptr.annotation` is the pointer to annotate (as | ||
with any call to this intrinsic). | ||
* The second parameter is the literal string `"sycl-properties"`. | ||
* The third parameter is the name of the source file (as with any call to this | ||
intrinsic). | ||
* The fourth parameter is the line number (as with any call to this intrinsic). | ||
* The fifth parameter is a metadata tuple with information about all of the | ||
properties. The first element of the tuple is a string literal with the name | ||
of the first property. The second element is the value of the first | ||
property. The third element is a string literal with the name of the second | ||
property, etc. Since each property has exactly one value, this tuple has an | ||
even number of elements. | ||
|
||
**NOTE**: Calls to the `@llvm.ptr.annotation` intrinsic function are known to | ||
disable many clang optimizations. As a result, properties added to a | ||
non-global variable will likely result in LLVM IR (and SPIR-V) that is not well | ||
gmlueck marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
@@ -597,18 +605,20 @@ types listed above. | |
|
||
Properties that are implemented using | ||
`[[__sycl_detail__::add_ir_annotations_member()]]`, are represented in LLVM IR | ||
as the fifth metadata parameter to the `@llvm.ptr.annotation` intrinsic | ||
function. This parameter is a tuple of metadata values with the following | ||
sequence: | ||
as the fifth parameter to the `@llvm.ptr.annotation` intrinsic function. This | ||
parameter is a pointer to a global variable with fields corresponding to the | ||
names and values of the properties in the following sequence: | ||
|
||
* Name of the first property | ||
* Value of the first property | ||
* Name of the second property | ||
* Value of the second property | ||
* Etc. | ||
|
||
Since metadata types are not limited to strings, there is no need to convert | ||
the property values to strings. | ||
Every field in the global variable pointed to by this parameter are string | ||
literals in seperate global variables. Property values are converted to strings | ||
in the same way as described above, except that the `nullptr` value and the | ||
empty string (`""`) is represented as `null` in the global variable field. | ||
|
||
|
||
## Filtering properties | ||
|
@@ -806,26 +816,57 @@ into one (or both) of the following: | |
In both cases, the decoration is a single **UserSemantic** decoration where the | ||
string literal is the same as the string literal in the LLVM annotation. | ||
|
||
When a SYCL structure member property needs to be represented in SPIR-V, | ||
however, we prefer to represent each property as an extended SPIR-V decoration | ||
rather than using a **UserSemantic** decoration. There is no existing | ||
mechanism in the SPIR-V LLVM Translator to generate extended decorations like | ||
this, so we propose the following new mechanism. | ||
An exception to this is for a selection of FPGA-related decorations. If these | ||
are supported during translation from LLVM IR to SPIR-V the corresponding | ||
decorations will be generated, and otherwise it will fall back to creating a | ||
single **UserSemantic** decoration. In general these decorations occur in the | ||
annotation string as a series of **{X}** and **{X:Y}** where **X** is a reserved | ||
name and **Y** is one or more words and numbers separated by a comma (**,**) or | ||
a colon (**:**), depending on the decoration. | ||
|
||
As such we propose an extension to this functionality with the following | ||
changes: | ||
|
||
* To bring it in line with the format of the metadata decorations, the parsing | ||
of these decorations should allow the use of SPIR-V decoration identifiers | ||
rather than reserved names. With this there need not be any agreement between | ||
the translator and LLVM IR producer, as the identifiers are specified by the | ||
SPIR-V specification. | ||
* For decorations parsed with decoration identifiers, only the comma delimiter | ||
is valid for separating decoration values. | ||
* In addition to words and numbers, string literals enclosed by quotation marks | ||
are allowed as decoration values. No escapes are planned for this, so all | ||
symbols between starting quotation mark and ending quotation mark are | ||
considered part of the string literal. | ||
|
||
When a member variable property needs to be represented in SPIR-V, the | ||
`sycl-post-link` tool converts the `@llvm.ptr.annotation` intrinsic call into a | ||
call to the SPIR-V intrinsic `__spirv_AddMemberDecoration` which has a metadata | ||
function argument that specifies the decorations as illustrated below: | ||
`sycl-post-link` tool converts the `@llvm.ptr.annotation` intrinsic call | ||
produced by `[[__sycl_detail__::add_ir_annotations_member()]]` into another | ||
`@llvm.ptr.annotation` intrinsic call using this format. For example: | ||
|
||
``` | ||
%annotated_ptr = call i8* __spirv_AddMemberDecoration(i8* %ptr, metadata !0) | ||
; Contains decorations: | ||
; * 7744 with no value. | ||
; * 7745 with 20 and "str 1" as the values. | ||
@.str = private unnamed_addr constant [24 x i8] c"{7744}{7745:20,\22str 1\22}\00", | ||
section "llvm.metadata" | ||
@.str.1 = private unnamed_addr constant [9 x i8] c"file.cpp\00", | ||
section "llvm.metadata" | ||
|
||
!0 = !{!1, !2} ; Each operand in this metadata represents one | ||
; decoration. | ||
!1 = !{i32 7744} ; This is the integer value of the first decoration. | ||
!2 = !{i32 7745, i32 20} ; The first operand is the integer value of the | ||
; second decoration. Additional operands are | ||
; "extra operands" to the decoration. These | ||
; operands may be either integer literals or string | ||
; literals. | ||
define void @foo(i32* %ptr) { | ||
... | ||
|
||
; %0 points to the annotated member field. | ||
%2 = call i8* @llvm.ptr.annotation.p0i8(i8* nonnull %0, | ||
i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0), | ||
i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i64 0, i64 0), | ||
i32 3, | ||
i8* null) | ||
|
||
... | ||
} | ||
``` | ||
|
||
**NOTE**: To allow backwards compatibility with the old format, reverse | ||
translation of decorations will produce a decorations in the annotation string | ||
following the old format if the decoration had a reserved name. |
Uh oh!
There was an error while loading. Please reload this page.