-
Notifications
You must be signed in to change notification settings - Fork 797
[SYCL][ESIMD] Refactor ESIMD kernel support in FE. #2747
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 2 commits
8e521ff
d4f5813
e5ab3ef
f9c7ea2
b442079
95053d4
bb9c41e
d3b1493
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 |
---|---|---|
|
@@ -1162,6 +1162,19 @@ def SYCLRegisterNum : InheritableAttr { | |
let PragmaAttributeSupport = 0; | ||
} | ||
|
||
// Used to mark kernel pointer parameters which correspond to the original | ||
// lambda's captured accessor. FE turns it to some metadata required by the | ||
// ESIMD Back-End. | ||
// Not supposed to be used directly in the source - SYCL device compiler FE | ||
// automatically adds it for ESIMD kernels. | ||
def SYCLSimdAccessorPtr : InheritableAttr { | ||
let Spellings = [GNU<"esimd_acc_ptr">, Declspec<"esimd_acc_ptr">]; | ||
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. I guess we don't need spelling if this attribute is not supposed to be used in the source. 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. ok |
||
let Subjects = SubjectList<[ParmVar]>; | ||
let LangOpts = [SYCLExplicitSIMD]; | ||
let Documentation = [SYCLSimdAccessorPtrDocs]; | ||
let PragmaAttributeSupport = 0; | ||
} | ||
|
||
def SYCLScope : Attr { | ||
// No spelling, as this attribute can't be created in the source code. | ||
let Spellings = []; | ||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -332,7 +332,7 @@ class SYCLIntegrationHeader { | |||||
/// Signals that subsequent parameter descriptor additions will go to | ||||||
/// the kernel with given name. Starts new kernel invocation descriptor. | ||||||
void startKernel(StringRef KernelName, QualType KernelNameType, | ||||||
StringRef KernelStableName, SourceLocation Loc); | ||||||
StringRef KernelStableName, SourceLocation Loc, bool IsESIMD); | ||||||
|
||||||
/// Adds a kernel parameter descriptor to current kernel invocation | ||||||
/// descriptor. | ||||||
|
@@ -375,6 +375,9 @@ class SYCLIntegrationHeader { | |||||
|
||||||
SourceLocation KernelLocation; | ||||||
|
||||||
/// Whether this kernel is an ESIMD one. | ||||||
bool IsESIMD; | ||||||
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. How about
Suggested change
To make it clear that this flag is about kernel and not language options, for example. 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. ok |
||||||
|
||||||
/// Descriptor of kernel actual parameters. | ||||||
SmallVector<KernelParamDesc, 8> Params; | ||||||
|
||||||
|
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -1439,6 +1439,10 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn, | |||||
// MDNode for the intel_buffer_location attribute. | ||||||
SmallVector<llvm::Metadata *, 8> argSYCLBufferLocationAttr; | ||||||
|
||||||
// MDNode for listing ESIMD kernel pointer arguments originating from | ||||||
// accessors | ||||||
SmallVector<llvm::Metadata *, 8> argESIMDAccPtrs; | ||||||
|
||||||
if (FD && CGF) | ||||||
for (unsigned i = 0, e = FD->getNumParams(); i != e; ++i) { | ||||||
const ParmVarDecl *parm = FD->getParamDecl(i); | ||||||
|
@@ -1570,6 +1574,10 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn, | |||||
? llvm::ConstantAsMetadata::get(CGF->Builder.getInt32( | ||||||
SYCLBufferLocationAttr->getLocationID())) | ||||||
: llvm::ConstantAsMetadata::get(CGF->Builder.getInt32(-1))); | ||||||
|
||||||
argESIMDAccPtrs.push_back( | ||||||
llvm::ConstantAsMetadata::get(CGF->Builder.getInt1( | ||||||
parm->getAttr<SYCLSimdAccessorPtrAttr>() != nullptr))); | ||||||
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. I think it will be a bit more optimal.
Suggested change
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. not sure. I want 0 or 1 is a clean input for getInt1. Non-null parm->getAttr() is neither 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. Sorry, I didn't get your statement. I thought that 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. Sorry, you are right. hasAttr is OK - will change |
||||||
} | ||||||
|
||||||
if (LangOpts.SYCLIsDevice && !LangOpts.SYCLExplicitSIMD) | ||||||
|
@@ -1586,6 +1594,8 @@ void CodeGenModule::GenOpenCLArgMetadata(llvm::Function *Fn, | |||||
llvm::MDNode::get(VMContext, argBaseTypeNames)); | ||||||
Fn->setMetadata("kernel_arg_type_qual", | ||||||
llvm::MDNode::get(VMContext, argTypeQuals)); | ||||||
Fn->setMetadata("kernel_arg_accessor_ptr", | ||||||
llvm::MDNode::get(VMContext, argESIMDAccPtrs)); | ||||||
if (getCodeGenOpts().EmitOpenCLArgMetadata) | ||||||
Fn->setMetadata("kernel_arg_name", | ||||||
llvm::MDNode::get(VMContext, argNames)); | ||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -8209,6 +8209,9 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, | |
case ParsedAttr::AT_SYCLRegisterNum: | ||
handleSYCLRegisterNumAttr(S, D, AL); | ||
break; | ||
case ParsedAttr::AT_SYCLSimdAccessorPtr: | ||
handleSimpleAttribute<SYCLSimdAccessorPtrAttr>(S, D, AL); | ||
break; | ||
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. I guess we won't need this part if we remove spelling. 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. ok |
||
case ParsedAttr::AT_Format: | ||
handleFormatAttr(S, D, AL); | ||
break; | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -57,6 +57,7 @@ enum KernelInvocationKind { | |
}; | ||
|
||
const static std::string InitMethodName = "__init"; | ||
const static std::string InitESIMDMethodName = "__init_esimd"; | ||
const static std::string FinalizeMethodName = "__finalize"; | ||
constexpr unsigned MaxKernelArgsSize = 2048; | ||
|
||
|
@@ -1700,7 +1701,8 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler { | |
bool isAccessorType = false) { | ||
const auto *RecordDecl = FieldTy->getAsCXXRecordDecl(); | ||
assert(RecordDecl && "The accessor/sampler must be a RecordDecl"); | ||
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, InitMethodName); | ||
const std::string &MethodName = KernelDecl->hasAttr<SYCLSimdAttr>() && isAccessorType ? InitESIMDMethodName : InitMethodName; | ||
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName); | ||
assert(InitMethod && "The accessor/sampler must have the __init method"); | ||
|
||
// Don't do -1 here because we count on this to be the first parameter added | ||
|
@@ -1709,9 +1711,14 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler { | |
for (const ParmVarDecl *Param : InitMethod->parameters()) { | ||
QualType ParamTy = Param->getType(); | ||
addParam(FD, ParamTy.getCanonicalType()); | ||
if (ParamTy.getTypePtr()->isPointerType() && isAccessorType) | ||
if (ParamTy.getTypePtr()->isPointerType() && isAccessorType) { | ||
handleAccessorPropertyList(Params.back(), RecordDecl, | ||
FD->getLocation()); | ||
if (KernelDecl->hasAttr<SYCLSimdAttr>()) | ||
// In ESIMD kernels accessor's pointer argument needs to be marked | ||
Params.back()->addAttr( | ||
SYCLSimdAccessorPtrAttr::CreateImplicit(SemaRef.getASTContext())); | ||
} | ||
} | ||
LastParamIndex = ParamIndex; | ||
return true; | ||
|
@@ -1805,7 +1812,8 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler { | |
QualType FieldTy) final { | ||
const auto *RecordDecl = FieldTy->getAsCXXRecordDecl(); | ||
assert(RecordDecl && "The accessor/sampler must be a RecordDecl"); | ||
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, InitMethodName); | ||
const std::string MethodName = KernelDecl->hasAttr<SYCLSimdAttr>() ? InitESIMDMethodName : InitMethodName; | ||
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName); | ||
assert(InitMethod && "The accessor/sampler must have the __init method"); | ||
|
||
// Don't do -1 here because we count on this to be the first parameter added | ||
|
@@ -1937,6 +1945,7 @@ class SyclKernelDeclCreator : public SyclKernelFieldHandler { | |
class SyclKernelArgsSizeChecker : public SyclKernelFieldHandler { | ||
SourceLocation KernelLoc; | ||
unsigned SizeOfParams = 0; | ||
bool IsSIMD = false; | ||
|
||
void addParam(QualType ArgTy) { | ||
SizeOfParams += | ||
|
@@ -1946,7 +1955,8 @@ class SyclKernelArgsSizeChecker : public SyclKernelFieldHandler { | |
bool handleSpecialType(QualType FieldTy) { | ||
const CXXRecordDecl *RecordDecl = FieldTy->getAsCXXRecordDecl(); | ||
assert(RecordDecl && "The accessor/sampler must be a RecordDecl"); | ||
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, InitMethodName); | ||
const std::string &MethodName = IsSIMD ? InitESIMDMethodName : InitMethodName; | ||
CXXMethodDecl *InitMethod = getMethodByName(RecordDecl, MethodName); | ||
assert(InitMethod && "The accessor/sampler must have the __init method"); | ||
for (const ParmVarDecl *Param : InitMethod->parameters()) | ||
addParam(Param->getType()); | ||
|
@@ -1955,8 +1965,8 @@ class SyclKernelArgsSizeChecker : public SyclKernelFieldHandler { | |
|
||
public: | ||
static constexpr const bool VisitInsideSimpleContainers = false; | ||
SyclKernelArgsSizeChecker(Sema &S, SourceLocation Loc) | ||
: SyclKernelFieldHandler(S), KernelLoc(Loc) {} | ||
SyclKernelArgsSizeChecker(Sema &S, SourceLocation Loc, bool IsSIMD) | ||
: SyclKernelFieldHandler(S), KernelLoc(Loc), IsSIMD(IsSIMD) {} | ||
|
||
~SyclKernelArgsSizeChecker() { | ||
if (SizeOfParams > MaxKernelArgsSize) | ||
|
@@ -2030,6 +2040,15 @@ class SyclKernelArgsSizeChecker : public SyclKernelFieldHandler { | |
using SyclKernelFieldHandler::handleSyclHalfType; | ||
}; | ||
|
||
static const CXXMethodDecl *getOperatorParens(const CXXRecordDecl *Rec) { | ||
for (const auto *D : Rec->decls()) { | ||
if (const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D)) | ||
kbobrovs marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (MD->getOverloadedOperator() == OO_Call) | ||
return MD; | ||
} | ||
return nullptr; | ||
} | ||
|
||
class SyclKernelBodyCreator : public SyclKernelFieldHandler { | ||
SyclKernelDeclCreator &DeclCreator; | ||
llvm::SmallVector<Stmt *, 16> BodyStmts; | ||
|
@@ -2345,6 +2364,13 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler { | |
return VD; | ||
} | ||
|
||
const std::string& getInitMethodName() const { | ||
const CXXMethodDecl *OpParens = getOperatorParens(KernelObj); | ||
bool IsSIMDKernel = | ||
(OpParens != nullptr) && OpParens->hasAttr<SYCLSimdAttr>(); | ||
return IsSIMDKernel ? InitESIMDMethodName : InitMethodName; | ||
} | ||
|
||
// Default inits the type, then calls the init-method in the body. | ||
bool handleSpecialType(FieldDecl *FD, QualType Ty) { | ||
addFieldInit(FD, Ty, None, | ||
|
@@ -2353,7 +2379,7 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler { | |
addFieldMemberExpr(FD, Ty); | ||
|
||
const auto *RecordDecl = Ty->getAsCXXRecordDecl(); | ||
createSpecialMethodCall(RecordDecl, InitMethodName, BodyStmts); | ||
createSpecialMethodCall(RecordDecl, getInitMethodName(), BodyStmts); | ||
|
||
removeFieldMemberExpr(FD, Ty); | ||
|
||
|
@@ -2363,7 +2389,7 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler { | |
bool handleSpecialType(const CXXBaseSpecifier &BS, QualType Ty) { | ||
const auto *RecordDecl = Ty->getAsCXXRecordDecl(); | ||
addBaseInit(BS, Ty, InitializationKind::CreateDefault(KernelCallerSrcLoc)); | ||
createSpecialMethodCall(RecordDecl, InitMethodName, BodyStmts); | ||
createSpecialMethodCall(RecordDecl, getInitMethodName(), BodyStmts); | ||
return true; | ||
} | ||
|
||
|
@@ -2487,7 +2513,7 @@ class SyclKernelBodyCreator : public SyclKernelFieldHandler { | |
// calls, so add them here instead. | ||
const auto *StreamDecl = Ty->getAsCXXRecordDecl(); | ||
|
||
createSpecialMethodCall(StreamDecl, InitMethodName, BodyStmts); | ||
createSpecialMethodCall(StreamDecl, getInitMethodName(), BodyStmts); | ||
createSpecialMethodCall(StreamDecl, FinalizeMethodName, FinalizeStmts); | ||
|
||
removeFieldMemberExpr(FD, Ty); | ||
|
@@ -2645,7 +2671,11 @@ class SyclKernelIntHeaderCreator : public SyclKernelFieldHandler { | |
const CXXRecordDecl *KernelObj, QualType NameType, | ||
StringRef Name, StringRef StableName) | ||
: SyclKernelFieldHandler(S), Header(H) { | ||
Header.startKernel(Name, NameType, StableName, KernelObj->getLocation()); | ||
const CXXMethodDecl *OpParens = getOperatorParens(KernelObj); | ||
bool IsSIMDKernel = | ||
(OpParens != nullptr) && OpParens->hasAttr<SYCLSimdAttr>(); | ||
|
||
Header.startKernel(Name, NameType, StableName, KernelObj->getLocation(), IsSIMDKernel); | ||
} | ||
|
||
bool handleSyclAccessorType(const CXXRecordDecl *RD, | ||
|
@@ -3012,7 +3042,10 @@ void Sema::CheckSYCLKernelCall(FunctionDecl *KernelFunc, SourceRange CallLoc, | |
SyclKernelDecompMarker DecompMarker(*this); | ||
SyclKernelFieldChecker FieldChecker(*this); | ||
SyclKernelUnionChecker UnionChecker(*this); | ||
SyclKernelArgsSizeChecker ArgsSizeChecker(*this, Args[0]->getExprLoc()); | ||
|
||
const CXXMethodDecl *OpParens = getOperatorParens(KernelObj); | ||
bool IsSIMD = (OpParens != nullptr) && OpParens->hasAttr<SYCLSimdAttr>(); | ||
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. nit: Those two lines are repeated multiple times. Maybe create a helper function? 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. ok |
||
SyclKernelArgsSizeChecker ArgsSizeChecker(*this, Args[0]->getExprLoc(), IsSIMD); | ||
|
||
KernelObjVisitor Visitor{*this}; | ||
SYCLKernelNameTypeVisitor KernelNameTypeVisitor(*this, Args[0]->getExprLoc(), | ||
|
@@ -3073,6 +3106,10 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, | |
if (KernelObj->isInvalidDecl()) | ||
return; | ||
|
||
const CXXMethodDecl *OpParens = getOperatorParens(KernelObj); | ||
bool IsSIMDKernel = | ||
(OpParens != nullptr) && OpParens->hasAttr<SYCLSimdAttr>(); | ||
|
||
// Calculate both names, since Integration headers need both. | ||
std::string CalculatedName, StableName; | ||
std::tie(CalculatedName, StableName) = | ||
|
@@ -3081,7 +3118,7 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, | |
: CalculatedName); | ||
SyclKernelDeclCreator kernel_decl(*this, KernelName, KernelObj->getLocation(), | ||
KernelCallerFunc->isInlined(), | ||
KernelCallerFunc->hasAttr<SYCLSimdAttr>()); | ||
IsSIMDKernel); | ||
SyclKernelBodyCreator kernel_body(*this, kernel_decl, KernelObj, | ||
KernelCallerFunc); | ||
SyclKernelIntHeaderCreator int_header( | ||
|
@@ -3795,6 +3832,8 @@ void SYCLIntegrationHeader::emit(raw_ostream &O) { | |
O << "getParamDesc(unsigned i) {\n"; | ||
O << " return kernel_signatures[i+" << CurStart << "];\n"; | ||
O << " }\n"; | ||
O << " __SYCL_DLL_LOCAL\n"; | ||
O << " static constexpr bool isESIMD() { return " << K.IsESIMD << "; }\n"; | ||
O << "};\n"; | ||
CurStart += N; | ||
} | ||
|
@@ -3824,12 +3863,14 @@ bool SYCLIntegrationHeader::emit(const StringRef &IntHeaderName) { | |
void SYCLIntegrationHeader::startKernel(StringRef KernelName, | ||
QualType KernelNameType, | ||
StringRef KernelStableName, | ||
SourceLocation KernelLocation) { | ||
SourceLocation KernelLocation, | ||
bool IsESIMDKernel) { | ||
KernelDescs.resize(KernelDescs.size() + 1); | ||
KernelDescs.back().Name = std::string(KernelName); | ||
KernelDescs.back().NameType = KernelNameType; | ||
KernelDescs.back().StableName = std::string(KernelStableName); | ||
KernelDescs.back().KernelLocation = KernelLocation; | ||
KernelDescs.back().IsESIMD = IsESIMDKernel; | ||
} | ||
|
||
void SYCLIntegrationHeader::addParamDesc(kernel_param_kind_t Kind, int Info, | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can move this information to the doc.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ok