Skip to content

Commit d2982c6

Browse files
[SYCL][Clang] Add __sycl_detail__::add_ir_annotations_member attribute (#5879)
These changes introduce the new `__sycl_detail__::add_ir_annotations_member`. This attribute is similar in behaviour to `__sycl_detail__::add_ir_attributes_*` attributes but will generate annotation intrinsic calls rather than LLVM IR attributes.
1 parent ff2f0f9 commit d2982c6

18 files changed

+2063
-0
lines changed

clang/include/clang/Basic/Attr.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1689,6 +1689,16 @@ def SYCLAddIRAttributesGlobalVariable : InheritableAttr {
16891689
let Documentation = [SYCLAddIRAttributesGlobalVariableDocs];
16901690
}
16911691

1692+
def SYCLAddIRAnnotationsMember : InheritableAttr {
1693+
let Spellings = [CXX11<"__sycl_detail__", "add_ir_annotations_member">];
1694+
let Args = [VariadicExprArgument<"Args">];
1695+
let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost];
1696+
let Subjects = SubjectList<[Field], ErrorDiag>;
1697+
let AcceptsExprPack = 1;
1698+
let AdditionalMembers = SYCLAddIRAttrCommonMembers.MemberCode;
1699+
let Documentation = [SYCLAddIRAnnotationsMemberDocs];
1700+
}
1701+
16921702
def C11NoReturn : InheritableAttr {
16931703
let Spellings = [Keyword<"_Noreturn">];
16941704
let Subjects = SubjectList<[Function], ErrorDiag>;

clang/include/clang/Basic/AttrDocs.td

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3611,6 +3611,83 @@ where the last N*2 are as described above.
36113611
}];
36123612
}
36133613

3614+
def SYCLAddIRAnnotationsMemberDocs : Documentation {
3615+
let Category = DocCatVariable;
3616+
let Heading = "add_ir_annotations_member";
3617+
let Content = [{
3618+
This attribute can be applied to a non-static field. Access to a field with this
3619+
attribute will generate a call to ``llvm.ptr.annotation`` with the arguments
3620+
paired.
3621+
The attribute must contain N*2 arguments. Each of the first N of these arguments
3622+
must be either string literals or ``constexpr const char *``. The following N
3623+
must be integer, floating point, character, boolean, ``const char *``, or an
3624+
enumeration as either a literal or ``constexpr`` value. The first N arguments
3625+
and the second N arguments are zipped into pairs when creating the call to
3626+
``llvm.ptr.annotation``, i.e. in the constant global variable pointed to by the
3627+
generated annotation intrinsic call, the N+1'th argument of the attribute will
3628+
occur after the first argument of the attribute, the N+2'th argument of the
3629+
attribute will occur after the second argument of the attribute, etc.
3630+
The generated call to ``llvm.ptr.annotation`` will have the following arguments
3631+
in this order:
3632+
* First argument is a pointer to the field.
3633+
* A pointer to a string literal in a constant global variable. This will
3634+
always be "sycl-properties".
3635+
* A pointer to a string literal in a constant global variable with the name of
3636+
the source file.
3637+
* The line number of the field declaration in the source file.
3638+
* A pointer to a constant global variable containing pointers to string
3639+
literals in constant global variables. These pointers to string literals
3640+
occur in pairs. If the second value of a pair was a ``nullptr`` or an empty
3641+
string then the pointer will be a null-pointer.
3642+
A pair will not be in the call to ``llvm.ptr.annotation`` if the first value of
3643+
the pair is an empty string.
3644+
3645+
.. code-block:: c++
3646+
3647+
struct Foo {
3648+
int *ptr
3649+
#ifdef __SYCL_DEVICE_ONLY__
3650+
[[__sycl_detail__::add_ir_annotations_member(
3651+
"Attr1", "Attr2", "Attribute value", 3.14)]]
3652+
#endif
3653+
;
3654+
};
3655+
// Accessing the 'ptr' field of 'Foo' will result in a call to
3656+
// 'llvm.ptr.annotation' with the second argument pointing to a constant
3657+
// global variable containing "sycl-properties" and the fifth argument
3658+
// pointing to a constant global variable with pointers to string literals
3659+
// "Attr1", "Attribute value", "Attr2", "3.14" in that order.
3660+
3661+
Optionally, the first argument of the attribute can be an initializer list
3662+
containing only string literals. This initializer list acts as a filter,
3663+
allowing only pairs with the first value in the initializer list to be
3664+
generated. If this intializer list is present, the attribute must have N*2+1
3665+
arguments, where the last N*2 are as described above.
3666+
3667+
.. code-block:: c++
3668+
3669+
struct Foo {
3670+
int *ptr
3671+
#ifdef __SYCL_DEVICE_ONLY__
3672+
[[__sycl_detail__::add_ir_annotations_member(
3673+
{"Attr2"}, "Attr1", "Attr2", "Attribute value", 3.14)]]
3674+
#endif
3675+
;
3676+
};
3677+
// Accessing the 'ptr' field of 'Foo' will result in a call to
3678+
// 'llvm.ptr.annotation' with the second argument pointing to a constant
3679+
// global variable containing "sycl-properties" and the fifth argument
3680+
// pointing to a constant global variable with pointers to string literals
3681+
// "Attr2", "3.14" in that order.
3682+
3683+
.. Note:: This attribute will only generate a call to ``llvm.ptr.annotation`` in
3684+
SYCL device code.
3685+
3686+
.. Note:: This attribute is intended as an internal implementation detail and is
3687+
not intended to be used by external users.
3688+
}];
3689+
}
3690+
36143691
def SYCLDeviceIndirectlyCallableDocs : Documentation {
36153692
let Category = DocCatFunction;
36163693
let Heading = "intel::device_indirectly_callable";

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10666,6 +10666,11 @@ class Sema final {
1066610666
void AddSYCLAddIRAttributesGlobalVariableAttr(Decl *D,
1066710667
const AttributeCommonInfo &CI,
1066810668
MutableArrayRef<Expr *> Args);
10669+
SYCLAddIRAnnotationsMemberAttr *
10670+
MergeSYCLAddIRAnnotationsMemberAttr(Decl *D,
10671+
const SYCLAddIRAnnotationsMemberAttr &A);
10672+
void AddSYCLAddIRAnnotationsMemberAttr(Decl *D, const AttributeCommonInfo &CI,
10673+
MutableArrayRef<Expr *> Args);
1066910674
void AddReqdWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
1067010675
Expr *XDim, Expr *YDim, Expr *ZDim);
1067110676
ReqdWorkGroupSizeAttr *

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4524,6 +4524,9 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,
45244524

45254525
// Emit attribute annotation for a field.
45264526
if (getLangOpts().SYCLIsDevice) {
4527+
if (field->hasAttr<SYCLAddIRAnnotationsMemberAttr>())
4528+
addr = EmitFieldSYCLAnnotations(field, addr);
4529+
45274530
SmallString<256> AnnotStr;
45284531
CGM.generateIntelFPGAAnnotation(field, AnnotStr);
45294532
if (!AnnotStr.empty())

clang/lib/CodeGen/CodeGenFunction.cpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2720,6 +2720,40 @@ Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
27202720
return Address(V, Addr.getElementType(), Addr.getAlignment());
27212721
}
27222722

2723+
llvm::Value *CodeGenFunction::EmitSYCLAnnotationCall(
2724+
llvm::Function *AnnotationFn, llvm::Value *AnnotatedVal,
2725+
SourceLocation Location, const SYCLAddIRAnnotationsMemberAttr *Attr) {
2726+
SmallVector<llvm::Value *, 5> Args = {
2727+
AnnotatedVal,
2728+
Builder.CreateBitCast(CGM.EmitAnnotationString("sycl-properties"),
2729+
Int8PtrTy),
2730+
Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
2731+
CGM.EmitAnnotationLineNo(Location), CGM.EmitSYCLAnnotationArgs(Attr)};
2732+
return Builder.CreateCall(AnnotationFn, Args);
2733+
}
2734+
2735+
Address CodeGenFunction::EmitFieldSYCLAnnotations(const FieldDecl *D,
2736+
Address Addr) {
2737+
const auto *SYCLAnnotAttr = D->getAttr<SYCLAddIRAnnotationsMemberAttr>();
2738+
assert(SYCLAnnotAttr && "no add_ir_annotations_member attribute");
2739+
llvm::Value *V = Addr.getPointer();
2740+
llvm::Type *VTy = V->getType();
2741+
auto *PTy = dyn_cast<llvm::PointerType>(VTy);
2742+
unsigned AS = PTy ? PTy->getAddressSpace() : 0;
2743+
llvm::Type *IntrType = VTy;
2744+
if (!VTy->getPointerElementType()->isIntegerTy())
2745+
IntrType = llvm::PointerType::getWithSamePointeeType(CGM.Int8PtrTy, AS);
2746+
llvm::Function *F =
2747+
CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation, IntrType);
2748+
2749+
if (VTy != IntrType)
2750+
V = Builder.CreateBitCast(V, IntrType);
2751+
V = EmitSYCLAnnotationCall(F, V, D->getLocation(), SYCLAnnotAttr);
2752+
if (VTy != IntrType)
2753+
V = Builder.CreateBitCast(V, VTy);
2754+
return Address(V, Addr.getElementType(), Addr.getAlignment());
2755+
}
2756+
27232757
Address CodeGenFunction::EmitIntelFPGAFieldAnnotations(const FieldDecl *D,
27242758
Address Addr,
27252759
StringRef AnnotStr) {

clang/lib/CodeGen/CodeGenFunction.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4508,6 +4508,16 @@ class CodeGenFunction : public CodeGenTypeCache {
45084508
/// annotation result.
45094509
Address EmitFieldAnnotations(const FieldDecl *D, Address V);
45104510

4511+
/// Emit a "sycl-properties" annotation call (intrinsic).
4512+
llvm::Value *
4513+
EmitSYCLAnnotationCall(llvm::Function *AnnotationFn,
4514+
llvm::Value *AnnotatedVal, SourceLocation Location,
4515+
const SYCLAddIRAnnotationsMemberAttr *Attr);
4516+
4517+
/// Emit sycl field annotations for given field & value. Returns the
4518+
/// annotation result.
4519+
Address EmitFieldSYCLAnnotations(const FieldDecl *D, Address V);
4520+
45114521
/// Emit Intel FPGA field annotations for the given field and value. Returns
45124522
/// the annotation result.
45134523
Address EmitIntelFPGAFieldAnnotations(const FieldDecl *D, Address V,

clang/lib/CodeGen/CodeGenModule.cpp

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2873,6 +2873,55 @@ void CodeGenModule::AddGlobalAnnotations(const ValueDecl *D,
28732873
Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation()));
28742874
}
28752875

2876+
llvm::Constant *CodeGenModule::EmitSYCLAnnotationArgs(
2877+
const SYCLAddIRAnnotationsMemberAttr *Attr) {
2878+
llvm::SmallVector<std::pair<std::string, std::string>, 4>
2879+
AnnotationNameValPairs =
2880+
Attr->getFilteredAttributeNameValuePairs(getContext());
2881+
if (AnnotationNameValPairs.empty())
2882+
return llvm::ConstantPointerNull::get(GlobalsInt8PtrTy);
2883+
2884+
// For each name-value pair of the SYCL annotation attribute, create an
2885+
// annotation string for it. This will be the annotation arguments. If the
2886+
// value is the empty string, use a null-pointer instead.
2887+
llvm::SmallVector<llvm::Constant *, 4> LLVMArgs;
2888+
llvm::FoldingSetNodeID ID;
2889+
LLVMArgs.reserve(AnnotationNameValPairs.size() * 2);
2890+
for (const std::pair<std::string, std::string> &NVP :
2891+
AnnotationNameValPairs) {
2892+
llvm::Constant *NameStrC = EmitAnnotationString(NVP.first);
2893+
llvm::Constant *ValueStrC =
2894+
NVP.second == "" ? llvm::ConstantPointerNull::get(GlobalsInt8PtrTy)
2895+
: EmitAnnotationString(NVP.second);
2896+
LLVMArgs.push_back(NameStrC);
2897+
LLVMArgs.push_back(ValueStrC);
2898+
ID.Add(NameStrC);
2899+
ID.Add(ValueStrC);
2900+
}
2901+
2902+
// If another SYCL annotation had the same arguments we can reuse the
2903+
// annotation value it created.
2904+
llvm::Constant *&LookupRef = SYCLAnnotationArgs[ID.ComputeHash()];
2905+
if (LookupRef)
2906+
return LookupRef;
2907+
2908+
// Create an anonymous struct global variable pointing to the annotation
2909+
// arguments in the order they were added above. This is the final constant
2910+
// used as the annotation value.
2911+
auto *Struct = llvm::ConstantStruct::getAnon(LLVMArgs);
2912+
auto *GV = new llvm::GlobalVariable(getModule(), Struct->getType(), true,
2913+
llvm::GlobalValue::PrivateLinkage, Struct,
2914+
".args");
2915+
GV->setSection(AnnotationSection);
2916+
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
2917+
auto *Bitcasted = llvm::ConstantExpr::getBitCast(GV, GlobalsInt8PtrTy);
2918+
2919+
// Set the look-up reference to the final annotation value for future
2920+
// annotations to reuse.
2921+
LookupRef = Bitcasted;
2922+
return Bitcasted;
2923+
}
2924+
28762925
void CodeGenModule::AddGlobalSYCLIRAttributes(llvm::GlobalVariable *GV,
28772926
const RecordDecl *RD) {
28782927
const auto *A = RD->getAttr<SYCLAddIRAttributesGlobalVariableAttr>();

clang/lib/CodeGen/CodeGenModule.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -410,6 +410,10 @@ class CodeGenModule : public CodeGenTypeCache {
410410
/// Used for uniquing of annotation arguments.
411411
llvm::DenseMap<unsigned, llvm::Constant *> AnnotationArgs;
412412

413+
/// Used for uniquing of SYCL annotation arguments. SYCL annotations are
414+
/// handled differently than regular annotations so they cannot share map.
415+
llvm::DenseMap<unsigned, llvm::Constant *> SYCLAnnotationArgs;
416+
413417
llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap;
414418

415419
llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap;
@@ -1310,6 +1314,10 @@ class CodeGenModule : public CodeGenTypeCache {
13101314
/// annotations are emitted during finalization of the LLVM code.
13111315
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);
13121316

1317+
/// Emit additional args of the annotation.
1318+
llvm::Constant *
1319+
EmitSYCLAnnotationArgs(const SYCLAddIRAnnotationsMemberAttr *Attr);
1320+
13131321
/// Add attributes from add_ir_attributes_global_variable on TND to GV.
13141322
void AddGlobalSYCLIRAttributes(llvm::GlobalVariable *GV,
13151323
const RecordDecl *RD);

clang/lib/Sema/SemaDecl.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2816,6 +2816,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
28162816
else if (const auto *A =
28172817
dyn_cast<SYCLAddIRAttributesGlobalVariableAttr>(Attr))
28182818
NewAttr = S.MergeSYCLAddIRAttributesGlobalVariableAttr(D, *A);
2819+
else if (const auto *A = dyn_cast<SYCLAddIRAnnotationsMemberAttr>(Attr))
2820+
NewAttr = S.MergeSYCLAddIRAnnotationsMemberAttr(D, *A);
28192821
else if (const auto *A = dyn_cast<ReqdWorkGroupSizeAttr>(Attr))
28202822
NewAttr = S.MergeReqdWorkGroupSizeAttr(D, *A);
28212823
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))

clang/lib/Sema/SemaDeclAttr.cpp

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7911,6 +7911,38 @@ static void handleSYCLAddIRAttributesGlobalVariableAttr(Sema &S, Decl *D,
79117911
S.AddSYCLAddIRAttributesGlobalVariableAttr(D, A, Args);
79127912
}
79137913

7914+
SYCLAddIRAnnotationsMemberAttr *Sema::MergeSYCLAddIRAnnotationsMemberAttr(
7915+
Decl *D, const SYCLAddIRAnnotationsMemberAttr &A) {
7916+
if (const auto *ExistingAttr = D->getAttr<SYCLAddIRAnnotationsMemberAttr>()) {
7917+
checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this);
7918+
return nullptr;
7919+
}
7920+
return A.clone(Context);
7921+
}
7922+
7923+
void Sema::AddSYCLAddIRAnnotationsMemberAttr(Decl *D,
7924+
const AttributeCommonInfo &CI,
7925+
MutableArrayRef<Expr *> Args) {
7926+
auto *Attr = SYCLAddIRAnnotationsMemberAttr::Create(Context, Args.data(),
7927+
Args.size(), CI);
7928+
if (evaluateAddIRAttributesArgs(Attr->args_begin(), Attr->args_size(), *this,
7929+
CI))
7930+
return;
7931+
D->addAttr(Attr);
7932+
}
7933+
7934+
static void handleSYCLAddIRAnnotationsMemberAttr(Sema &S, Decl *D,
7935+
const ParsedAttr &A) {
7936+
llvm::SmallVector<Expr *, 4> Args;
7937+
Args.reserve(A.getNumArgs());
7938+
for (unsigned I = 0; I < A.getNumArgs(); I++) {
7939+
assert(A.getArgAsExpr(I));
7940+
Args.push_back(A.getArgAsExpr(I));
7941+
}
7942+
7943+
S.AddSYCLAddIRAnnotationsMemberAttr(D, A, Args);
7944+
}
7945+
79147946
namespace {
79157947
struct IntrinToName {
79167948
uint32_t Id;
@@ -11389,6 +11421,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
1138911421
case ParsedAttr::AT_SYCLAddIRAttributesGlobalVariable:
1139011422
handleSYCLAddIRAttributesGlobalVariableAttr(S, D, AL);
1139111423
break;
11424+
case ParsedAttr::AT_SYCLAddIRAnnotationsMember:
11425+
handleSYCLAddIRAnnotationsMemberAttr(S, D, AL);
11426+
break;
1139211427

1139311428
// Swift attributes.
1139411429
case ParsedAttr::AT_SwiftAsyncName:

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -827,6 +827,18 @@ static void instantiateSYCLAddIRAttributesGlobalVariableAttr(
827827
S.AddSYCLAddIRAttributesGlobalVariableAttr(New, *A, Args);
828828
}
829829

830+
static void instantiateSYCLAddIRAnnotationsMemberAttr(
831+
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
832+
const SYCLAddIRAnnotationsMemberAttr *A, Decl *New) {
833+
EnterExpressionEvaluationContext ConstantEvaluated(
834+
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
835+
SmallVector<Expr *, 4> Args;
836+
if (S.SubstExprs(ArrayRef<Expr *>(A->args().begin(), A->args().end()),
837+
/*IsCall=*/false, TemplateArgs, Args))
838+
return;
839+
S.AddSYCLAddIRAnnotationsMemberAttr(New, *A, Args);
840+
}
841+
830842
static void instantiateWorkGroupSizeHintAttr(
831843
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
832844
const WorkGroupSizeHintAttr *A, Decl *New) {
@@ -1154,6 +1166,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
11541166
*this, TemplateArgs, SYCLAddIRAttributesGlobalVariable, New);
11551167
continue;
11561168
}
1169+
if (const auto *SYCLAddIRAnnotationsMember =
1170+
dyn_cast<SYCLAddIRAnnotationsMemberAttr>(TmplAttr)) {
1171+
instantiateSYCLAddIRAnnotationsMemberAttr(
1172+
*this, TemplateArgs, SYCLAddIRAnnotationsMember, New);
1173+
continue;
1174+
}
11571175
if (const auto *A = dyn_cast<WorkGroupSizeHintAttr>(TmplAttr)) {
11581176
instantiateWorkGroupSizeHintAttr(*this, TemplateArgs, A, New);
11591177
continue;

0 commit comments

Comments
 (0)