18 #include "llvm/Analysis/OptimizationRemarkEmitter.h"
19 #include "llvm/IR/Instructions.h"
22 using namespace clang;
23 using namespace CodeGen;
31 using DeclContextDesc = std::pair<clang::Decl::Kind, StringRef>;
38 static bool matchQualifiedTypeName(
const CXXRecordDecl *RecTy,
43 const auto *MD = dyn_cast<CXXMethodDecl>(&FD);
46 static std::array<Util::DeclContextDesc, 3> Scopes = {
47 Util::DeclContextDesc{clang::Decl::Kind::Namespace,
"sycl"},
48 Util::DeclContextDesc{clang::Decl::Kind::Namespace,
"_V1"},
49 Util::DeclContextDesc{Decl::Kind::ClassTemplateSpecialization,
"group"}};
50 if (!Util::matchQualifiedTypeName(MD->getParent(), Scopes))
52 return FD.
getName() ==
"parallel_for_work_item";
55 constexpr
char WG_SCOPE_MD_ID[] =
"work_group_scope";
56 constexpr
char WI_SCOPE_MD_ID[] =
"work_item_scope";
57 constexpr
char PFWI_MD_ID[] =
"parallel_for_work_item";
58 constexpr
char ATTR_GENX_VOLATILE[] =
"genx_volatile";
59 constexpr
char ATTR_GENX_BYTE_OFFSET[] =
"genx_byte_offset";
67 F.setMetadata(
"sycl_explicit_simd", llvm::MDNode::get(F.getContext(), {}));
70 if (
const auto *A = FD.
getAttr<SYCLIntelESimdVectorizeAttr>())
71 if (
const auto *DeclExpr = cast<ConstantExpr>(A->getValue())) {
73 DeclExpr->getResultAsAPSInt().toString(Str);
74 F.addFnAttr(
"CMGenxSIMT", Str);
80 switch (
Scope->getLevel()) {
81 case SYCLScopeAttr::Level::WorkGroup:
82 F.setMetadata(WG_SCOPE_MD_ID, llvm::MDNode::get(F.getContext(), {}));
84 case SYCLScopeAttr::Level::WorkItem:
85 F.setMetadata(WI_SCOPE_MD_ID, llvm::MDNode::get(F.getContext(), {}));
89 F.setMetadata(PFWI_MD_ID, llvm::MDNode::get(F.getContext(), {}));
92 llvm_unreachable(
"unknown sycl scope");
99 assert(
Scope &&
Scope->isWorkGroup() &&
"work group scope expected");
111 assert(
Scope->isWorkItem() &&
"auto var must be of work item scope");
112 auto *AI = dyn_cast<llvm::AllocaInst>(Addr);
113 assert(AI &&
"AllocaInst expected as local var address");
114 AI->setMetadata(WI_SCOPE_MD_ID, llvm::MDNode::get(AI->getContext(), {}));
120 SYCLRegisterNumAttr *RegAttr = D.
getAttr<SYCLRegisterNumAttr>();
123 auto *GlobVar = cast<llvm::GlobalVariable>(Addr);
124 GlobVar->addAttribute(ATTR_GENX_VOLATILE);
125 GlobVar->addAttribute(ATTR_GENX_BYTE_OFFSET,
126 Twine(RegAttr->getNumber()).str());
131 bool Util::matchQualifiedTypeName(
const CXXRecordDecl *RecTy,
138 const auto *Ctx = cast<DeclContext>(RecTy);
141 for (
const auto &
Scope : llvm::reverse(Scopes)) {
144 if (DK !=
Scope.first)
148 case clang::Decl::Kind::ClassTemplateSpecialization:
150 case clang::Decl::Kind::CXXRecord:
151 Name = cast<CXXRecordDecl>(Ctx)->getName();
153 case clang::Decl::Kind::Namespace:
154 Name = cast<NamespaceDecl>(Ctx)->getName();
157 llvm_unreachable(
"matchQualifiedTypeName: decl kind not supported");
159 if (Name !=
Scope.second)
161 Ctx = Ctx->getParent();
163 return Ctx->isTranslationUnit();
Defines the clang::SourceLocation class and associated facilities.
Represents a C++ struct/union/class.
bool actOnFunctionStart(const FunctionDecl &FD, llvm::Function &F)
void emitWorkGroupLocalVarDecl(CodeGenFunction &CGF, const VarDecl &D)
bool actOnGlobalVarEmit(CodeGenModule &CGM, const VarDecl &D, llvm::Value *Addr)
bool actOnAutoVarEmit(CodeGenFunction &CGF, const VarDecl &D, llvm::Value *Addr)
CodeGenFunction - This class organizes the per-function state that is used while generating LLVM code...
void EmitStaticVarDecl(const VarDecl &D, llvm::GlobalValue::LinkageTypes Linkage)
This class organizes the cross-function state that is used while generating LLVM code.
Kind
Lists the kind of concrete classes of Decl.
Represents a function declaration or definition.
StringRef getName() const
Get the name of identifier for this declaration as a StringRef.
Scope - A scope is a transient data structure that is used while parsing the program.
Represents a variable declaration or definition.
The JSON file list parser is used to communicate input to InstallAPI.