-
Notifications
You must be signed in to change notification settings - Fork 768
WIP Replace local clone with SYCL kernel object #1568
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 all commits
b2f3950
3eae199
5c643d6
cce4455
11aa9a2
4b8a799
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 |
---|---|---|
|
@@ -628,6 +628,16 @@ static ParamDesc makeParamDesc(const FieldDecl *Src, QualType Ty) { | |
Ctx.getTrivialTypeSourceInfo(Ty)); | ||
} | ||
|
||
// Creates a parameter descriptor for kernel object | ||
static ParamDesc makeParamDesc(const CXXRecordDecl *Src, QualType Ty) { | ||
ASTContext &Ctx = Src->getASTContext(); | ||
// There is no name available for lambda object. Name for all | ||
// kernel types (lambda and functor) is set as _arg_kernelObject. | ||
std::string Name = "_arg_kernelObject"; | ||
return std::make_tuple(Ty, &Ctx.Idents.get(Name), | ||
Ctx.getTrivialTypeSourceInfo(Ty)); | ||
} | ||
|
||
static ParamDesc makeParamDesc(ASTContext &Ctx, const CXXBaseSpecifier &Src, | ||
QualType Ty) { | ||
// TODO: There is no name for the base available, but duplicate names are | ||
|
@@ -721,12 +731,17 @@ static void VisitAccessorWrapper(CXXRecordDecl *Owner, ParentTy &Parent, | |
// A visitor function that dispatches to functions as defined in | ||
// SyclKernelFieldHandler for the purposes of kernel generation. | ||
template <typename... Handlers> | ||
static void VisitRecordFields(RecordDecl::field_range Fields, | ||
static void VisitRecordFields(CXXRecordDecl *KernelObject, | ||
Handlers &... handlers) { | ||
|
||
QualType KernelType = QualType(KernelObject->getTypeForDecl(), 0); | ||
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. Are these only allowed to be top-level things? Can you clarify how this feature is supposed to work? I don't get it yet. 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. We're adding the kernel object as a parameter of the kernel function (just like we did with the fields). Currently in the kernel body, a kernel object clone is generated and initialized using the fields of kernel function. The clone is then subsequently used in kernel body code. We're now exploring the possibility of getting rid of the clone entirely and using this kernel object |
||
(void)std::initializer_list<int>{ | ||
(handlers.handleKernelObject(KernelObject, KernelType), 0)...}; | ||
|
||
#define KF_FOR_EACH(FUNC) \ | ||
(void)std::initializer_list<int> { (handlers.FUNC(Field, FieldTy), 0)... } | ||
|
||
for (const auto &Field : Fields) { | ||
for (const auto &Field : KernelObject->fields()) { | ||
QualType FieldTy = Field->getType(); | ||
|
||
if (Util::isSyclAccessorType(FieldTy)) | ||
|
@@ -781,6 +796,7 @@ template <typename Derived> class SyclKernelFieldHandler { | |
virtual void handlePointerType(FieldDecl *, QualType) {} | ||
virtual void handleArrayType(FieldDecl *, QualType) {} | ||
virtual void handleScalarType(FieldDecl *, QualType) {} | ||
virtual void handleKernelObject(CXXRecordDecl *, QualType) {} | ||
// Most handlers shouldn't be handling this, just the field checker. | ||
virtual void handleOtherType(FieldDecl *, QualType) {} | ||
|
||
|
@@ -830,6 +846,16 @@ class SyclKernelFieldChecker | |
<< 1 << FieldTy; | ||
} | ||
} | ||
void handleKernelObject(CXXRecordDecl *KernelObject, | ||
QualType KernelType) final { | ||
// TODO: Is this check correct? SYCL spec only talks about kernel defined as | ||
// named function objects. What about lambda functions? | ||
/*if (!KernelObject->isStandardLayoutType()) | ||
IsInvalid = | ||
Diag.Report(KernelObject->getLocation(), | ||
diag::err_sycl_non_std_layout_type) | ||
<< KernelType;*/ | ||
} | ||
|
||
// We should be able to handle this, so we made it part of the visitor, but | ||
// this is 'to be implemented'. | ||
|
@@ -860,6 +886,11 @@ class SyclKernelDeclCreator | |
addParam(newParamDesc, FieldTy); | ||
} | ||
|
||
void addParam(const CXXRecordDecl *KernelObject, QualType KernelType) { | ||
ParamDesc newParamDesc = makeParamDesc(KernelObject, KernelType); | ||
addParam(newParamDesc, KernelType); | ||
} | ||
|
||
void addParam(const CXXBaseSpecifier &BS, QualType FieldTy) { | ||
ParamDesc newParamDesc = | ||
makeParamDesc(SemaRef.getASTContext(), BS, FieldTy); | ||
|
@@ -985,12 +1016,9 @@ class SyclKernelDeclCreator | |
addParam(FD, ModTy); | ||
} | ||
|
||
void handleScalarType(FieldDecl *FD, QualType FieldTy) final { | ||
addParam(FD, FieldTy); | ||
} | ||
|
||
// TODO: Accessors in structs | ||
void handleStructType(FieldDecl *FD, QualType FieldTy) final { | ||
addParam(FD, FieldTy); | ||
// addParam(FD, FieldTy); | ||
} | ||
|
||
void handleSyclStreamType(FieldDecl *FD, QualType FieldTy) final { | ||
|
@@ -1002,6 +1030,11 @@ class SyclKernelDeclCreator | |
// See https://github.com/intel/llvm/issues/1552 | ||
} | ||
|
||
void handleKernelObject(CXXRecordDecl *KernelObject, | ||
QualType KernelType) final { | ||
addParam(KernelObject, KernelType); | ||
} | ||
|
||
void setBody(CompoundStmt *KB) { KernelDecl->setBody(KB); } | ||
|
||
FunctionDecl *getKernelDecl() { return KernelDecl; } | ||
|
@@ -1010,16 +1043,15 @@ class SyclKernelDeclCreator | |
return ArrayRef<ParmVarDecl *>(std::begin(Params) + LastParamIndex, | ||
std::end(Params)); | ||
} | ||
|
||
ParmVarDecl *getKernelObjectParam() { return Params.front(); } | ||
}; | ||
|
||
class SyclKernelBodyCreator | ||
: public SyclKernelFieldHandler<SyclKernelBodyCreator> { | ||
SyclKernelDeclCreator &DeclCreator; | ||
llvm::SmallVector<Stmt *, 16> BodyStmts; | ||
llvm::SmallVector<Stmt *, 16> FinalizeStmts; | ||
llvm::SmallVector<Expr *, 16> InitExprs; | ||
VarDecl *KernelObjClone; | ||
InitializedEntity VarEntity; | ||
CXXRecordDecl *KernelObj; | ||
llvm::SmallVector<Expr *, 16> MemberExprBases; | ||
FunctionDecl *KernelCallerFunc; | ||
|
@@ -1029,22 +1061,24 @@ class SyclKernelBodyCreator | |
// statements in advance to allocate it, so we cannot do this as we go along. | ||
CompoundStmt *createKernelBody() { | ||
|
||
Expr *ILE = new (SemaRef.getASTContext()) InitListExpr( | ||
SemaRef.getASTContext(), SourceLocation(), InitExprs, SourceLocation()); | ||
ILE->setType(QualType(KernelObj->getTypeForDecl(), 0)); | ||
KernelObjClone->setInit(ILE); | ||
Stmt *FunctionBody = KernelCallerFunc->getBody(); | ||
|
||
ParmVarDecl *KernelObjParam = *(KernelCallerFunc->param_begin()); | ||
// Kernel object parameter from kernel caller function | ||
ParmVarDecl *KernelCallerObjParam = *(KernelCallerFunc->param_begin()); | ||
// Kernel object parameter from generated kernel. | ||
ParmVarDecl *KernelObjParam = DeclCreator.getKernelObjectParam(); | ||
|
||
// DeclRefExpr with valid source location but with decl which is not marked | ||
// as used is invalid. | ||
KernelObjClone->setIsUsed(); | ||
KernelObjParam->setIsUsed(); | ||
std::pair<DeclaratorDecl *, DeclaratorDecl *> MappingPair = | ||
std::make_pair(KernelObjParam, KernelObjClone); | ||
std::make_pair(KernelCallerObjParam, KernelObjParam); | ||
|
||
// Push the Kernel function scope to ensure the scope isn't empty | ||
SemaRef.PushFunctionScope(); | ||
|
||
// Replacing all references to kernel caller function parameter in kernel | ||
// body with references to kernel object parameter in generated kernel. | ||
KernelBodyTransform KBT(MappingPair, SemaRef); | ||
Stmt *NewBody = KBT.TransformStmt(FunctionBody).get(); | ||
BodyStmts.push_back(NewBody); | ||
|
@@ -1094,26 +1128,13 @@ class SyclKernelBodyCreator | |
return Result; | ||
} | ||
|
||
// TODO: Correct Stream + Accessors | ||
void createExprForStructOrScalar(FieldDecl *FD) { | ||
ParmVarDecl *KernelParameter = | ||
DeclCreator.getParamVarDeclsForCurrentField()[0]; | ||
InitializedEntity Entity = | ||
InitializedEntity::InitializeMember(FD, &VarEntity); | ||
QualType ParamType = KernelParameter->getOriginalType(); | ||
Expr *DRE = SemaRef.BuildDeclRefExpr(KernelParameter, ParamType, VK_LValue, | ||
SourceLocation()); | ||
if (FD->getType()->isPointerType() && | ||
FD->getType()->getPointeeType().getAddressSpace() != | ||
ParamType->getPointeeType().getAddressSpace()) | ||
DRE = ImplicitCastExpr::Create(SemaRef.Context, FD->getType(), | ||
CK_AddressSpaceConversion, DRE, nullptr, | ||
VK_RValue); | ||
InitializationKind InitKind = | ||
InitializationKind::CreateCopy(SourceLocation(), SourceLocation()); | ||
InitializationSequence InitSeq(SemaRef, Entity, InitKind, DRE); | ||
|
||
ExprResult MemberInit = InitSeq.Perform(SemaRef, Entity, InitKind, DRE); | ||
InitExprs.push_back(MemberInit.get()); | ||
} | ||
|
||
void createSpecialMethodCall(const CXXRecordDecl *SpecialClass, Expr *Base, | ||
|
@@ -1153,32 +1174,8 @@ class SyclKernelBodyCreator | |
BodyStmts.push_back(Call); | ||
} | ||
|
||
// FIXME Avoid creation of kernel obj clone. | ||
// See https://github.com/intel/llvm/issues/1544 for details. | ||
static VarDecl *createKernelObjClone(ASTContext &Ctx, DeclContext *DC, | ||
CXXRecordDecl *KernelObj) { | ||
TypeSourceInfo *TSInfo = | ||
KernelObj->isLambda() ? KernelObj->getLambdaTypeInfo() : nullptr; | ||
VarDecl *VD = VarDecl::Create( | ||
Ctx, DC, SourceLocation(), SourceLocation(), KernelObj->getIdentifier(), | ||
QualType(KernelObj->getTypeForDecl(), 0), TSInfo, SC_None); | ||
|
||
return VD; | ||
} | ||
|
||
void handleSpecialType(FieldDecl *FD, QualType Ty) { | ||
const auto *RecordDecl = Ty->getAsCXXRecordDecl(); | ||
// Perform initialization only if it is field of kernel object | ||
if (MemberExprBases.size() == 1) { | ||
InitializedEntity Entity = | ||
InitializedEntity::InitializeMember(FD, &VarEntity); | ||
// Initialize with the default constructor. | ||
InitializationKind InitKind = | ||
InitializationKind::CreateDefault(SourceLocation()); | ||
InitializationSequence InitSeq(SemaRef, Entity, InitKind, None); | ||
ExprResult MemberInit = InitSeq.Perform(SemaRef, Entity, InitKind, None); | ||
InitExprs.push_back(MemberInit.get()); | ||
} | ||
createSpecialMethodCall(RecordDecl, MemberExprBases.back(), InitMethodName, | ||
FD); | ||
} | ||
|
@@ -1188,20 +1185,8 @@ class SyclKernelBodyCreator | |
CXXRecordDecl *KernelObj, | ||
FunctionDecl *KernelCallerFunc) | ||
: SyclKernelFieldHandler(S), DeclCreator(DC), | ||
KernelObjClone(createKernelObjClone(S.getASTContext(), | ||
DC.getKernelDecl(), KernelObj)), | ||
VarEntity(InitializedEntity::InitializeVariable(KernelObjClone)), | ||
KernelObj(KernelObj), KernelCallerFunc(KernelCallerFunc) { | ||
markParallelWorkItemCalls(); | ||
|
||
Stmt *DS = new (S.Context) DeclStmt(DeclGroupRef(KernelObjClone), | ||
SourceLocation(), SourceLocation()); | ||
BodyStmts.push_back(DS); | ||
DeclRefExpr *KernelObjCloneRef = DeclRefExpr::Create( | ||
S.Context, NestedNameSpecifierLoc(), SourceLocation(), KernelObjClone, | ||
false, DeclarationNameInfo(), QualType(KernelObj->getTypeForDecl(), 0), | ||
VK_LValue); | ||
MemberExprBases.push_back(KernelObjCloneRef); | ||
} | ||
|
||
~SyclKernelBodyCreator() { | ||
|
@@ -1237,15 +1222,40 @@ class SyclKernelBodyCreator | |
} | ||
|
||
void handlePointerType(FieldDecl *FD, QualType FieldTy) final { | ||
createExprForStructOrScalar(FD); | ||
ParmVarDecl *KernelParameter = | ||
DeclCreator.getParamVarDeclsForCurrentField()[0]; | ||
QualType ParamType = KernelParameter->getOriginalType(); | ||
Expr *DRE = SemaRef.BuildDeclRefExpr(KernelParameter, ParamType, VK_LValue, | ||
SourceLocation()); | ||
if (FD->getType()->isPointerType() && | ||
FD->getType()->getPointeeType().getAddressSpace() != | ||
ParamType->getPointeeType().getAddressSpace()) | ||
DRE = ImplicitCastExpr::Create(SemaRef.Context, FD->getType(), | ||
CK_AddressSpaceConversion, DRE, nullptr, | ||
VK_RValue); | ||
|
||
MemberExpr *KernelObjectPointerField = | ||
BuildMemberExpr(MemberExprBases.back(), FD); | ||
Expr *AssignPointerParameter = BinaryOperator::Create( | ||
SemaRef.getASTContext(), KernelObjectPointerField, DRE, BO_Assign, | ||
FieldTy, VK_LValue, OK_Ordinary, SourceLocation(), | ||
FPOptions(SemaRef.getASTContext().getLangOpts())); | ||
|
||
BodyStmts.push_back(AssignPointerParameter); | ||
} | ||
|
||
// TODO: Accessors in structs | ||
void handleStructType(FieldDecl *FD, QualType FieldTy) final { | ||
createExprForStructOrScalar(FD); | ||
// createExprForStructOrScalar(FD); | ||
} | ||
|
||
void handleScalarType(FieldDecl *FD, QualType FieldTy) final { | ||
createExprForStructOrScalar(FD); | ||
void handleKernelObject(CXXRecordDecl *KernelObject, QualType KernelType) { | ||
ParmVarDecl *KernelParameter = | ||
DeclCreator.getParamVarDeclsForCurrentField()[0]; | ||
QualType ParamType = KernelParameter->getOriginalType(); | ||
Expr *KernelObjRef = SemaRef.BuildDeclRefExpr(KernelParameter, ParamType, | ||
VK_LValue, SourceLocation()); | ||
MemberExprBases.push_back(KernelObjRef); | ||
} | ||
|
||
void enterStruct(const CXXRecordDecl *, FieldDecl *FD) final { | ||
|
@@ -1376,6 +1386,14 @@ class SyclKernelIntHeaderCreator | |
CurStruct = FD->getType()->getAsCXXRecordDecl(); | ||
CurOffset += SemaRef.getASTContext().getFieldOffset(FD) / 8; | ||
} | ||
void handleKernelObject(CXXRecordDecl *KernelObject, | ||
QualType KernelType) final { | ||
uint64_t Size = | ||
SemaRef.getASTContext().getTypeSizeInChars(KernelType).getQuantity(); | ||
// Offset for kernel object is 0 | ||
Header.addParamDesc(SYCLIntegrationHeader::kind_std_layout, | ||
static_cast<unsigned>(Size), 0); | ||
} | ||
|
||
void leaveStruct(const CXXRecordDecl *RD, FieldDecl *FD) final { | ||
CurStruct = RD; | ||
|
@@ -1447,7 +1465,7 @@ void Sema::ConstructOpenCLKernel(FunctionDecl *KernelCallerFunc, | |
StableName); | ||
|
||
ConstructingOpenCLKernel = true; | ||
VisitRecordFields(KernelLambda->fields(), checker, kernel_decl, kernel_body, | ||
VisitRecordFields(KernelLambda, checker, kernel_decl, kernel_body, | ||
int_header); | ||
ConstructingOpenCLKernel = false; | ||
} | ||
|
Uh oh!
There was an error while loading. Please reload this page.