Skip to content

[SYCL][Clang] Add __sycl_detail__::add_ir_annotations_member attribute #5879

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

Merged
merged 6 commits into from
Apr 5, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions clang/include/clang/Basic/Attr.td
Original file line number Diff line number Diff line change
Expand Up @@ -1689,6 +1689,16 @@ def SYCLAddIRAttributesGlobalVariable : InheritableAttr {
let Documentation = [SYCLAddIRAttributesGlobalVariableDocs];
}

def SYCLAddIRAnnotationsMember : InheritableAttr {
let Spellings = [CXX11<"__sycl_detail__", "add_ir_annotations_member">];
let Args = [VariadicExprArgument<"Args">];
let LangOpts = [SYCLIsDevice, SilentlyIgnoreSYCLIsHost];
let Subjects = SubjectList<[Field], ErrorDiag>;
let AcceptsExprPack = 1;
let AdditionalMembers = SYCLAddIRAttrCommonMembers.MemberCode;
let Documentation = [SYCLAddIRAnnotationsMemberDocs];
}

def C11NoReturn : InheritableAttr {
let Spellings = [Keyword<"_Noreturn">];
let Subjects = SubjectList<[Function], ErrorDiag>;
Expand Down
77 changes: 77 additions & 0 deletions clang/include/clang/Basic/AttrDocs.td
Original file line number Diff line number Diff line change
Expand Up @@ -3611,6 +3611,83 @@ where the last N*2 are as described above.
}];
}

def SYCLAddIRAnnotationsMemberDocs : Documentation {
let Category = DocCatVariable;
let Heading = "add_ir_annotations_member";
let Content = [{
This attribute can be applied to a non-static field. Access to a field with this
attribute will generate a call to ``llvm.ptr.annotation`` with the arguments
paired.
The attribute must contain N*2 arguments. Each of the first N of these arguments
must be either string literals or ``constexpr const char *``. The following N
must be integer, floating point, character, boolean, ``const char *``, or an
enumeration as either a literal or ``constexpr`` value. The first N arguments
and the second N arguments are zipped into pairs when creating the call to
``llvm.ptr.annotation``, i.e. in the constant global variable pointed to by the
generated annotation intrinsic call, the N+1'th argument of the attribute will
occur after the first argument of the attribute, the N+2'th argument of the
attribute will occur after the second argument of the attribute, etc.
The generated call to ``llvm.ptr.annotation`` will have the following arguments
in this order:
* First argument is a pointer to the field.
* A pointer to a string literal in a constant global variable. This will
always be "sycl-properties".
* A pointer to a string literal in a constant global variable with the name of
the source file.
* The line number of the field declaration in the source file.
* A pointer to a constant global variable containing pointers to string
literals in constant global variables. These pointers to string literals
occur in pairs. If the second value of a pair was a ``nullptr`` or an empty
string then the pointer will be a null-pointer.
A pair will not be in the call to ``llvm.ptr.annotation`` if the first value of
the pair is an empty string.

.. code-block:: c++

struct Foo {
int *ptr
#ifdef __SYCL_DEVICE_ONLY__
[[__sycl_detail__::add_ir_annotations_member(
"Attr1", "Attr2", "Attribute value", 3.14)]]
#endif
;
};
// Accessing the 'ptr' field of 'Foo' will result in a call to
// 'llvm.ptr.annotation' with the second argument pointing to a constant
// global variable containing "sycl-properties" and the fifth argument
// pointing to a constant global variable with pointers to string literals
// "Attr1", "Attribute value", "Attr2", "3.14" in that order.

Optionally, the first argument of the attribute can be an initializer list
containing only string literals. This initializer list acts as a filter,
allowing only pairs with the first value in the initializer list to be
generated. If this intializer list is present, the attribute must have N*2+1
arguments, where the last N*2 are as described above.

.. code-block:: c++

struct Foo {
int *ptr
#ifdef __SYCL_DEVICE_ONLY__
[[__sycl_detail__::add_ir_annotations_member(
{"Attr2"}, "Attr1", "Attr2", "Attribute value", 3.14)]]
#endif
;
};
// Accessing the 'ptr' field of 'Foo' will result in a call to
// 'llvm.ptr.annotation' with the second argument pointing to a constant
// global variable containing "sycl-properties" and the fifth argument
// pointing to a constant global variable with pointers to string literals
// "Attr2", "3.14" in that order.

.. Note:: This attribute will only generate a call to ``llvm.ptr.annotation`` in
SYCL device code.

.. Note:: This attribute is intended as an internal implementation detail and is
not intended to be used by external users.
}];
}

def SYCLDeviceIndirectlyCallableDocs : Documentation {
let Category = DocCatFunction;
let Heading = "intel::device_indirectly_callable";
Expand Down
5 changes: 5 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -10637,6 +10637,11 @@ class Sema final {
void AddSYCLAddIRAttributesGlobalVariableAttr(Decl *D,
const AttributeCommonInfo &CI,
MutableArrayRef<Expr *> Args);
SYCLAddIRAnnotationsMemberAttr *
MergeSYCLAddIRAnnotationsMemberAttr(Decl *D,
const SYCLAddIRAnnotationsMemberAttr &A);
void AddSYCLAddIRAnnotationsMemberAttr(Decl *D, const AttributeCommonInfo &CI,
MutableArrayRef<Expr *> Args);
void AddReqdWorkGroupSizeAttr(Decl *D, const AttributeCommonInfo &CI,
Expr *XDim, Expr *YDim, Expr *ZDim);
ReqdWorkGroupSizeAttr *
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4518,6 +4518,9 @@ LValue CodeGenFunction::EmitLValueForField(LValue base,

// Emit attribute annotation for a field.
if (getLangOpts().SYCLIsDevice) {
if (field->hasAttr<SYCLAddIRAnnotationsMemberAttr>())
addr = EmitFieldSYCLAnnotations(field, addr);

SmallString<256> AnnotStr;
CGM.generateIntelFPGAAnnotation(field, AnnotStr);
if (!AnnotStr.empty())
Expand Down
34 changes: 34 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2721,6 +2721,40 @@ Address CodeGenFunction::EmitFieldAnnotations(const FieldDecl *D,
return Address(V, Addr.getElementType(), Addr.getAlignment());
}

llvm::Value *CodeGenFunction::EmitSYCLAnnotationCall(
llvm::Function *AnnotationFn, llvm::Value *AnnotatedVal,
SourceLocation Location, const SYCLAddIRAnnotationsMemberAttr *Attr) {
SmallVector<llvm::Value *, 5> Args = {
AnnotatedVal,
Builder.CreateBitCast(CGM.EmitAnnotationString("sycl-properties"),
Int8PtrTy),
Builder.CreateBitCast(CGM.EmitAnnotationUnit(Location), Int8PtrTy),
CGM.EmitAnnotationLineNo(Location), CGM.EmitSYCLAnnotationArgs(Attr)};
return Builder.CreateCall(AnnotationFn, Args);
}

Address CodeGenFunction::EmitFieldSYCLAnnotations(const FieldDecl *D,
Address Addr) {
const auto *SYCLAnnotAttr = D->getAttr<SYCLAddIRAnnotationsMemberAttr>();
assert(SYCLAnnotAttr && "no add_ir_annotations_member attribute");
llvm::Value *V = Addr.getPointer();
llvm::Type *VTy = V->getType();
auto *PTy = dyn_cast<llvm::PointerType>(VTy);
unsigned AS = PTy ? PTy->getAddressSpace() : 0;
llvm::Type *IntrType = VTy;
if (!VTy->getPointerElementType()->isIntegerTy())
IntrType = llvm::PointerType::getWithSamePointeeType(CGM.Int8PtrTy, AS);
llvm::Function *F =
CGM.getIntrinsic(llvm::Intrinsic::ptr_annotation, IntrType);

if (VTy != IntrType)
V = Builder.CreateBitCast(V, IntrType);
V = EmitSYCLAnnotationCall(F, V, D->getLocation(), SYCLAnnotAttr);
if (VTy != IntrType)
V = Builder.CreateBitCast(V, VTy);
return Address(V, Addr.getElementType(), Addr.getAlignment());
}

Address CodeGenFunction::EmitIntelFPGAFieldAnnotations(const FieldDecl *D,
Address Addr,
StringRef AnnotStr) {
Expand Down
10 changes: 10 additions & 0 deletions clang/lib/CodeGen/CodeGenFunction.h
Original file line number Diff line number Diff line change
Expand Up @@ -4504,6 +4504,16 @@ class CodeGenFunction : public CodeGenTypeCache {
/// annotation result.
Address EmitFieldAnnotations(const FieldDecl *D, Address V);

/// Emit a "sycl-properties" annotation call (intrinsic).
llvm::Value *
EmitSYCLAnnotationCall(llvm::Function *AnnotationFn,
llvm::Value *AnnotatedVal, SourceLocation Location,
const SYCLAddIRAnnotationsMemberAttr *Attr);

/// Emit sycl field annotations for given field & value. Returns the
/// annotation result.
Address EmitFieldSYCLAnnotations(const FieldDecl *D, Address V);

/// Emit Intel FPGA field annotations for the given field and value. Returns
/// the annotation result.
Address EmitIntelFPGAFieldAnnotations(const FieldDecl *D, Address V,
Expand Down
49 changes: 49 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2873,6 +2873,55 @@ void CodeGenModule::AddGlobalAnnotations(const ValueDecl *D,
Annotations.push_back(EmitAnnotateAttr(GV, I, D->getLocation()));
}

llvm::Constant *CodeGenModule::EmitSYCLAnnotationArgs(
const SYCLAddIRAnnotationsMemberAttr *Attr) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would appreciate some comments in this code.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely! I have added comments. Let me know if you think it is sufficient.

llvm::SmallVector<std::pair<std::string, std::string>, 4>
AnnotationNameValPairs =
Attr->getFilteredAttributeNameValuePairs(getContext());
if (AnnotationNameValPairs.empty())
return llvm::ConstantPointerNull::get(GlobalsInt8PtrTy);

// For each name-value pair of the SYCL annotation attribute, create an
// annotation string for it. This will be the annotation arguments. If the
// value is the empty string, use a null-pointer instead.
llvm::SmallVector<llvm::Constant *, 4> LLVMArgs;
llvm::FoldingSetNodeID ID;
LLVMArgs.reserve(AnnotationNameValPairs.size() * 2);
for (const std::pair<std::string, std::string> &NVP :
AnnotationNameValPairs) {
llvm::Constant *NameStrC = EmitAnnotationString(NVP.first);
llvm::Constant *ValueStrC =
NVP.second == "" ? llvm::ConstantPointerNull::get(GlobalsInt8PtrTy)
: EmitAnnotationString(NVP.second);
LLVMArgs.push_back(NameStrC);
LLVMArgs.push_back(ValueStrC);
ID.Add(NameStrC);
ID.Add(ValueStrC);
}

// If another SYCL annotation had the same arguments we can reuse the
// annotation value it created.
llvm::Constant *&LookupRef = SYCLAnnotationArgs[ID.ComputeHash()];
if (LookupRef)
return LookupRef;

// Create an anonymous struct global variable pointing to the annotation
// arguments in the order they were added above. This is the final constant
// used as the annotation value.
auto *Struct = llvm::ConstantStruct::getAnon(LLVMArgs);
auto *GV = new llvm::GlobalVariable(getModule(), Struct->getType(), true,
llvm::GlobalValue::PrivateLinkage, Struct,
".args");
GV->setSection(AnnotationSection);
GV->setUnnamedAddr(llvm::GlobalValue::UnnamedAddr::Global);
auto *Bitcasted = llvm::ConstantExpr::getBitCast(GV, GlobalsInt8PtrTy);

// Set the look-up reference to the final annotation value for future
// annotations to reuse.
LookupRef = Bitcasted;
return Bitcasted;
}

void CodeGenModule::AddGlobalSYCLIRAttributes(llvm::GlobalVariable *GV,
const RecordDecl *RD) {
const auto *A = RD->getAttr<SYCLAddIRAttributesGlobalVariableAttr>();
Expand Down
8 changes: 8 additions & 0 deletions clang/lib/CodeGen/CodeGenModule.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,6 +410,10 @@ class CodeGenModule : public CodeGenTypeCache {
/// Used for uniquing of annotation arguments.
llvm::DenseMap<unsigned, llvm::Constant *> AnnotationArgs;

/// Used for uniquing of SYCL annotation arguments. SYCL annotations are
/// handled differently than regular annotations so they cannot share map.
llvm::DenseMap<unsigned, llvm::Constant *> SYCLAnnotationArgs;

llvm::StringMap<llvm::GlobalVariable *> CFConstantStringMap;

llvm::DenseMap<llvm::Constant *, llvm::GlobalVariable *> ConstantStringMap;
Expand Down Expand Up @@ -1308,6 +1312,10 @@ class CodeGenModule : public CodeGenTypeCache {
/// annotations are emitted during finalization of the LLVM code.
void AddGlobalAnnotations(const ValueDecl *D, llvm::GlobalValue *GV);

/// Emit additional args of the annotation.
llvm::Constant *
EmitSYCLAnnotationArgs(const SYCLAddIRAnnotationsMemberAttr *Attr);

/// Add attributes from add_ir_attributes_global_variable on TND to GV.
void AddGlobalSYCLIRAttributes(llvm::GlobalVariable *GV,
const RecordDecl *RD);
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2805,6 +2805,8 @@ static bool mergeDeclAttribute(Sema &S, NamedDecl *D,
else if (const auto *A =
dyn_cast<SYCLAddIRAttributesGlobalVariableAttr>(Attr))
NewAttr = S.MergeSYCLAddIRAttributesGlobalVariableAttr(D, *A);
else if (const auto *A = dyn_cast<SYCLAddIRAnnotationsMemberAttr>(Attr))
NewAttr = S.MergeSYCLAddIRAnnotationsMemberAttr(D, *A);
else if (const auto *A = dyn_cast<ReqdWorkGroupSizeAttr>(Attr))
NewAttr = S.MergeReqdWorkGroupSizeAttr(D, *A);
else if (Attr->shouldInheritEvenIfAlreadyPresent() || !DeclHasAttr(D, Attr))
Expand Down
35 changes: 35 additions & 0 deletions clang/lib/Sema/SemaDeclAttr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7903,6 +7903,38 @@ static void handleSYCLAddIRAttributesGlobalVariableAttr(Sema &S, Decl *D,
S.AddSYCLAddIRAttributesGlobalVariableAttr(D, A, Args);
}

SYCLAddIRAnnotationsMemberAttr *Sema::MergeSYCLAddIRAnnotationsMemberAttr(
Decl *D, const SYCLAddIRAnnotationsMemberAttr &A) {
if (const auto *ExistingAttr = D->getAttr<SYCLAddIRAnnotationsMemberAttr>()) {
checkSYCLAddIRAttributesMergeability(A, *ExistingAttr, *this);
return nullptr;
}
return A.clone(Context);
}

void Sema::AddSYCLAddIRAnnotationsMemberAttr(Decl *D,
const AttributeCommonInfo &CI,
MutableArrayRef<Expr *> Args) {
auto *Attr = SYCLAddIRAnnotationsMemberAttr::Create(Context, Args.data(),
Args.size(), CI);
if (evaluateAddIRAttributesArgs(Attr->args_begin(), Attr->args_size(), *this,
CI))
return;
D->addAttr(Attr);
}

static void handleSYCLAddIRAnnotationsMemberAttr(Sema &S, Decl *D,
const ParsedAttr &A) {
llvm::SmallVector<Expr *, 4> Args;
Args.reserve(A.getNumArgs());
for (unsigned I = 0; I < A.getNumArgs(); I++) {
assert(A.getArgAsExpr(I));
Args.push_back(A.getArgAsExpr(I));
}

S.AddSYCLAddIRAnnotationsMemberAttr(D, A, Args);
}

namespace {
struct IntrinToName {
uint32_t Id;
Expand Down Expand Up @@ -11381,6 +11413,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
case ParsedAttr::AT_SYCLAddIRAttributesGlobalVariable:
handleSYCLAddIRAttributesGlobalVariableAttr(S, D, AL);
break;
case ParsedAttr::AT_SYCLAddIRAnnotationsMember:
handleSYCLAddIRAnnotationsMemberAttr(S, D, AL);
break;

// Swift attributes.
case ParsedAttr::AT_SwiftAsyncName:
Expand Down
18 changes: 18 additions & 0 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -828,6 +828,18 @@ static void instantiateSYCLAddIRAttributesGlobalVariableAttr(
S.AddSYCLAddIRAttributesGlobalVariableAttr(New, *A, Args);
}

static void instantiateSYCLAddIRAnnotationsMemberAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const SYCLAddIRAnnotationsMemberAttr *A, Decl *New) {
EnterExpressionEvaluationContext ConstantEvaluated(
S, Sema::ExpressionEvaluationContext::ConstantEvaluated);
SmallVector<Expr *, 4> Args;
if (S.SubstExprs(ArrayRef<Expr *>(A->args().begin(), A->args().end()),
/*IsCall=*/false, TemplateArgs, Args))
return;
S.AddSYCLAddIRAnnotationsMemberAttr(New, *A, Args);
}

static void instantiateWorkGroupSizeHintAttr(
Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs,
const WorkGroupSizeHintAttr *A, Decl *New) {
Expand Down Expand Up @@ -1155,6 +1167,12 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs,
*this, TemplateArgs, SYCLAddIRAttributesGlobalVariable, New);
continue;
}
if (const auto *SYCLAddIRAnnotationsMember =
dyn_cast<SYCLAddIRAnnotationsMemberAttr>(TmplAttr)) {
instantiateSYCLAddIRAnnotationsMemberAttr(
*this, TemplateArgs, SYCLAddIRAnnotationsMember, New);
continue;
}
if (const auto *A = dyn_cast<WorkGroupSizeHintAttr>(TmplAttr)) {
instantiateWorkGroupSizeHintAttr(*this, TemplateArgs, A, New);
continue;
Expand Down
Loading