Skip to content

Commit f6420c7

Browse files
[SYCL][Doc] Adjust design for compile-time properties through add_ir_annotations_member (#5884)
* [SYCL][Doc] Adjust design for compile-time properties through add_ir_annotations_member During implementation of the attribute and translation of annotations on fields, the design was conflicting with existing features. This commit makes the following design changes: * Change the `llvm.ptr.annotation` intrinsic call produced by `[[__sycl_detail__::add_ir_annotations_member()]]` to use a pointer to a constant global variable instead of metadata. This is done to adhere to the signature of the intrinsic. * Change the representation consumed by the translator from a new SPIR-V builtin to an extended version of existing decoration parsing using `llvm.ptr.annotation`. Implementation of these are in review #5879 and KhronosGroup/SPIRV-LLVM-Translator#1446 Signed-off-by: Larsen, Steffen <steffen.larsen@intel.com>
1 parent a1b42aa commit f6420c7

File tree

1 file changed

+87
-46
lines changed

1 file changed

+87
-46
lines changed

sycl/doc/design/CompileTimeProperties.md

Lines changed: 87 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -460,25 +460,50 @@ When the device compiler generates code to reference the decorated member
460460
variable, it emits a call to the LLVM intrinsic function
461461
[`@llvm.ptr.annotation`][10] that annotates the pointer to that member
462462
variables, similar to the way the existing `[[clang::annotate()]]` attribute
463-
works. Illustrating this with some simplified LLVM IR that matches the example
464-
code above:
463+
works.
465464

466465
[10]: <https://llvm.org/docs/LangRef.html#llvm-ptr-annotation-intrinsic>
467466

467+
The front-end encodes the properties from the C++ attribute
468+
`[[__sycl_detail__::add_ir_annotations_member()]]` into the
469+
`@llvm.ptr.annotation` call as follows:
470+
471+
* The first parameter to `@llvm.ptr.annotation` is the pointer to annotate (as
472+
with any call to this intrinsic).
473+
* The second parameter is the literal string `"sycl-properties"`.
474+
* The third parameter is the name of the source file (as with any call to this
475+
intrinsic).
476+
* The fourth parameter is the line number (as with any call to this intrinsic).
477+
* The fifth parameter is a pointer to a constant global variable. The type of
478+
this variable is an anonymous structure. The first field of the structure is
479+
a pointer to a string literal representing the name of the first property. The
480+
second field of the structure is a pointer to a string literal representing
481+
the value of the first property. The third field of the structure is a pointer
482+
to a string literal representing the name of the second property, etc.
483+
Since each property has exactly one value, this tuple has an even number of
484+
elements. Pointers to property value strings may be a null-pointer, signalling
485+
a property without a value.
486+
487+
The resulting LLVM IR for the previous example would be:
488+
468489
```
469490
@.str = private unnamed_addr constant [16 x i8] c"sycl-properties\00",
470491
section "llvm.metadata"
471492
@.str.1 = private unnamed_addr constant [9 x i8] c"file.cpp\00",
472493
section "llvm.metadata"
473-
@.str.2 = private unnamed_addr constant [9 x i8] c"sycl-foo\00", align 1
474-
@.str.3 = private unnamed_addr constant [9 x i8] c"sycl-bar\00", align 1
494+
@.str.2 = private unnamed_addr constant [9 x i8] c"sycl-foo\00",
495+
section "llvm.metadata"
496+
@.str.3 = private unnamed_addr constant [9 x i8] c"sycl-bar\00",
497+
section "llvm.metadata"
498+
@.str.4 = private unnamed_addr constant [3 x i8] c"32\00",
499+
section "llvm.metadata"
475500
476-
@.args = private unnamed_addr constant { [9 x i8]*, i8*, [9 x i8]*, i32 }
501+
@.args = private unnamed_addr constant { [9 x i8]*, i8*, [9 x i8]*, [3 x i8]* }
477502
{
478503
[9 x i8]* @.str.2, ; Name of first property "sycl-foo"
479504
i8* null, ; Null indicates this property has no value
480505
[9 x i8]* @.str.3, ; Name of second property "sycl-bar"
481-
i32 32 ; Value of second property
506+
[3 x i8]* @.str.4 ; Value of second property
482507
},
483508
section "llvm.metadata"
484509
@@ -492,31 +517,14 @@ define void @foo(i32* %ptr) {
492517
i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0),
493518
i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i64 0, i64 0),
494519
i32 3,
495-
i8* bitcast ({ [9 x i8]*, i8*, [9 x i8]*, i32 }* @.args to i8*))
520+
i8* bitcast ({ [9 x i8]*, i8*, [9 x i8]*, [3 x i8]* }* @.args to i8*))
496521
497522
%3 = bitcast i8* %2 to i32**
498523
store i32* %ptr, i32** %3
499524
ret void
500525
}
501526
```
502527

503-
The front-end encodes the properties from the C++ attribute
504-
`[[__sycl_detail__::add_ir_annotations_member()]]` into the
505-
`@llvm.ptr.annotation` call as follows:
506-
507-
* The first parameter to `@llvm.ptr.annotation` is the pointer to annotate (as
508-
with any call to this intrinsic).
509-
* The second parameter is the literal string `"sycl-properties"`.
510-
* The third parameter is the name of the source file (as with any call to this
511-
intrinsic).
512-
* The fourth parameter is the line number (as with any call to this intrinsic).
513-
* The fifth parameter is a metadata tuple with information about all of the
514-
properties. The first element of the tuple is a string literal with the name
515-
of the first property. The second element is the value of the first
516-
property. The third element is a string literal with the name of the second
517-
property, etc. Since each property has exactly one value, this tuple has an
518-
even number of elements.
519-
520528
**NOTE**: Calls to the `@llvm.ptr.annotation` intrinsic function are known to
521529
disable many clang optimizations. As a result, properties added to a
522530
non-global variable will likely result in LLVM IR (and SPIR-V) that is not well
@@ -592,18 +600,20 @@ types listed above.
592600

593601
Properties that are implemented using
594602
`[[__sycl_detail__::add_ir_annotations_member()]]`, are represented in LLVM IR
595-
as the fifth metadata parameter to the `@llvm.ptr.annotation` intrinsic
596-
function. This parameter is a tuple of metadata values with the following
597-
sequence:
603+
as the fifth parameter to the `@llvm.ptr.annotation` intrinsic function. This
604+
parameter is a pointer to a global variable with fields corresponding to the
605+
names and values of the properties in the following sequence:
598606

599607
* Name of the first property
600608
* Value of the first property
601609
* Name of the second property
602610
* Value of the second property
603611
* Etc.
604612

605-
Since metadata types are not limited to strings, there is no need to convert
606-
the property values to strings.
613+
Every field in the global variable pointed to by this parameter are string
614+
literals in seperate global variables. Property values are converted to strings
615+
in the same way as described above, except that the `nullptr` value and the
616+
empty string (`""`) is represented as `null` in the global variable field.
607617

608618

609619
## Filtering properties
@@ -801,26 +811,57 @@ into one (or both) of the following:
801811
In both cases, the decoration is a single **UserSemantic** decoration where the
802812
string literal is the same as the string literal in the LLVM annotation.
803813

804-
When a SYCL structure member property needs to be represented in SPIR-V,
805-
however, we prefer to represent each property as an extended SPIR-V decoration
806-
rather than using a **UserSemantic** decoration. There is no existing
807-
mechanism in the SPIR-V LLVM Translator to generate extended decorations like
808-
this, so we propose the following new mechanism.
814+
An exception to this is for a selection of FPGA-related decorations. If these
815+
are supported during translation from LLVM IR to SPIR-V the corresponding
816+
decorations will be generated, and otherwise it will fall back to creating a
817+
single **UserSemantic** decoration. In general these decorations occur in the
818+
annotation string as a series of **{X}** and **{X:Y}** where **X** is a reserved
819+
name and **Y** is one or more words and numbers separated by a comma (**,**) or
820+
a colon (**:**), depending on the decoration.
821+
822+
As such we propose an extension to this functionality with the following
823+
changes:
824+
825+
* To bring it in line with the format of the metadata decorations, the parsing
826+
of these decorations should allow the use of SPIR-V decoration identifiers
827+
rather than reserved names. With this there need not be any agreement between
828+
the translator and LLVM IR producer, as the identifiers are specified by the
829+
SPIR-V specification.
830+
* For decorations parsed with decoration identifiers, only the comma delimiter
831+
is valid for separating decoration values.
832+
* In addition to words and numbers, string literals enclosed by quotation marks
833+
are allowed as decoration values. No escapes are planned for this, so all
834+
symbols between starting quotation mark and ending quotation mark are
835+
considered part of the string literal.
809836

810837
When a member variable property needs to be represented in SPIR-V, the
811-
`sycl-post-link` tool converts the `@llvm.ptr.annotation` intrinsic call into a
812-
call to the SPIR-V intrinsic `__spirv_AddMemberDecoration` which has a metadata
813-
function argument that specifies the decorations as illustrated below:
838+
`sycl-post-link` tool converts the `@llvm.ptr.annotation` intrinsic call
839+
produced by `[[__sycl_detail__::add_ir_annotations_member()]]` into another
840+
`@llvm.ptr.annotation` intrinsic call using this format. For example:
814841

815842
```
816-
%annotated_ptr = call i8* __spirv_AddMemberDecoration(i8* %ptr, metadata !0)
843+
; Contains decorations:
844+
; * 7744 with no value.
845+
; * 7745 with 20 and "str 1" as the values.
846+
@.str = private unnamed_addr constant [24 x i8] c"{7744}{7745:20,\22str 1\22}\00",
847+
section "llvm.metadata"
848+
@.str.1 = private unnamed_addr constant [9 x i8] c"file.cpp\00",
849+
section "llvm.metadata"
817850
818-
!0 = !{!1, !2} ; Each operand in this metadata represents one
819-
; decoration.
820-
!1 = !{i32 7744} ; This is the integer value of the first decoration.
821-
!2 = !{i32 7745, i32 20} ; The first operand is the integer value of the
822-
; second decoration. Additional operands are
823-
; "extra operands" to the decoration. These
824-
; operands may be either integer literals or string
825-
; literals.
851+
define void @foo(i32* %ptr) {
852+
...
853+
854+
; %0 points to the annotated member field.
855+
%2 = call i8* @llvm.ptr.annotation.p0i8(i8* nonnull %0,
856+
i8* getelementptr inbounds ([16 x i8], [16 x i8]* @.str, i64 0, i64 0),
857+
i8* getelementptr inbounds ([9 x i8], [9 x i8]* @.str.1, i64 0, i64 0),
858+
i32 3,
859+
i8* null)
860+
861+
...
862+
}
826863
```
864+
865+
**NOTE**: To allow backwards compatibility with the old format, reverse
866+
translation of decorations will produce a decorations in the annotation string
867+
following the old format if the decoration had a reserved name.

0 commit comments

Comments
 (0)