diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 62e044d902202..78fd2f9575089 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -1287,13 +1287,18 @@ def SYCLIntelSchedulerTargetFmaxMhz : InheritableAttr { def SYCLIntelMaxWorkGroupSize : InheritableAttr { let Spellings = [CXX11<"intelfpga","max_work_group_size">, CXX11<"intel","max_work_group_size">]; - let Args = [UnsignedArgument<"XDim">, - UnsignedArgument<"YDim">, - UnsignedArgument<"ZDim">]; + let Args = [ExprArgument<"XDim">, + ExprArgument<"YDim">, + ExprArgument<"ZDim">]; let LangOpts = [SYCLIsDevice, SYCLIsHost]; let Subjects = SubjectList<[Function], ErrorDiag>; - let Documentation = [SYCLIntelMaxWorkGroupSizeAttrDocs]; let PragmaAttributeSupport = 0; + let AdditionalMembers = [{ + ArrayRef dimensions() const { + return {getXDim(), getYDim(), getZDim()}; + } + }]; + let Documentation = [SYCLIntelMaxWorkGroupSizeAttrDocs]; } def SYCLIntelMaxGlobalWorkDim : InheritableAttr { @@ -2806,9 +2811,15 @@ def ReqdWorkGroupSize : InheritableAttr { let Spellings = [GNU<"reqd_work_group_size">, CXX11<"intel","reqd_work_group_size">, CXX11<"cl","reqd_work_group_size">]; - let Args = [UnsignedArgument<"XDim">, DefaultUnsignedArgument<"YDim", 1>, - DefaultUnsignedArgument<"ZDim", 1>]; + let Args = [ExprArgument<"XDim">, + ExprArgument<"YDim", /*optional*/1>, + ExprArgument<"ZDim", /*optional*/1>]; let Subjects = SubjectList<[Function], ErrorDiag>; + let AdditionalMembers = [{ + ArrayRef dimensions() const { + return {getXDim(), getYDim(), getZDim()}; + } + }]; let Documentation = [ReqdWorkGroupSizeAttrDocs]; } diff --git a/clang/include/clang/Basic/DiagnosticGroups.td b/clang/include/clang/Basic/DiagnosticGroups.td index 4b42a37fd33aa..96229d366d2fb 100644 --- a/clang/include/clang/Basic/DiagnosticGroups.td +++ b/clang/include/clang/Basic/DiagnosticGroups.td @@ -667,8 +667,10 @@ def NSReturnsMismatch : DiagGroup<"nsreturns-mismatch">; def IndependentClassAttribute : DiagGroup<"IndependentClass-attribute">; def UnknownAttributes : DiagGroup<"unknown-attributes">; def IgnoredAttributes : DiagGroup<"ignored-attributes">; +def AcceptedAttributes : DiagGroup<"accepted-attributes">; def Attributes : DiagGroup<"attributes", [UnknownAttributes, - IgnoredAttributes]>; + IgnoredAttributes, + AcceptedAttributes]>; def UnknownSanitizers : DiagGroup<"unknown-sanitizers">; def UnnamedTypeTemplateArgs : DiagGroup<"unnamed-type-template-args", [CXX98CompatUnnamedTypeTemplateArgs]>; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 8548280f848a0..fed2ea93d2223 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -11207,6 +11207,10 @@ def warn_attribute_spelling_deprecated : Warning< InGroup; def note_spelling_suggestion : Note< "did you mean to use %0 instead?">; +def warn_attribute_requires_non_negative_integer_argument : Warning< + "the resulting value of the %0 attribute %select{first|second|third}1" + " parameter is always non-negative after implicit conversion">, + InGroup; // errors of expect.with.probability def err_probability_not_constant_float : Error< diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 7528fb3a6faa8..d5ef03b50e5bd 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -10081,6 +10081,10 @@ class Sema final { template void addIntelSYCLSingleArgFunctionAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E); + template + void addIntelSYCLTripleArgFunctionAttr(Decl *D, const AttributeCommonInfo &CI, + Expr *XDimExpr, Expr *YDimExpr, + Expr *ZDimExpr); /// AddAlignedAttr - Adds an aligned attribute to a particular declaration. void AddAlignedAttr(Decl *D, const AttributeCommonInfo &CI, Expr *E, bool IsPackExpansion); diff --git a/clang/lib/CodeGen/CodeGenFunction.cpp b/clang/lib/CodeGen/CodeGenFunction.cpp index 5c947cc66b42d..8c92970bdf22d 100644 --- a/clang/lib/CodeGen/CodeGenFunction.cpp +++ b/clang/lib/CodeGen/CodeGenFunction.cpp @@ -620,11 +620,22 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, } if (const ReqdWorkGroupSizeAttr *A = FD->getAttr()) { + llvm::LLVMContext &Context = getLLVMContext(); + Optional XDimVal = + A->getXDim()->getIntegerConstantExpr(FD->getASTContext()); + Optional YDimVal = + A->getYDim()->getIntegerConstantExpr(FD->getASTContext()); + Optional ZDimVal = + A->getZDim()->getIntegerConstantExpr(FD->getASTContext()); llvm::Metadata *AttrMDArgs[] = { - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("reqd_work_group_size", llvm::MDNode::get(Context, AttrMDArgs)); + llvm::ConstantAsMetadata::get( + Builder.getInt32(XDimVal->getZExtValue())), + llvm::ConstantAsMetadata::get( + Builder.getInt32(YDimVal->getZExtValue())), + llvm::ConstantAsMetadata::get( + Builder.getInt32(ZDimVal->getZExtValue()))}; + Fn->setMetadata("reqd_work_group_size", + llvm::MDNode::get(Context, AttrMDArgs)); } if (const IntelReqdSubGroupSizeAttr *A = @@ -670,16 +681,6 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, llvm::MDNode::get(Context, AttrMDArgs)); } - if (const SYCLIntelMaxWorkGroupSizeAttr *A = - FD->getAttr()) { - llvm::Metadata *AttrMDArgs[] = { - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getXDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getYDim())), - llvm::ConstantAsMetadata::get(Builder.getInt32(A->getZDim()))}; - Fn->setMetadata("max_work_group_size", - llvm::MDNode::get(Context, AttrMDArgs)); - } - if (const SYCLIntelMaxGlobalWorkDimAttr *A = FD->getAttr()) { llvm::LLVMContext &Context = getLLVMContext(); @@ -692,6 +693,26 @@ void CodeGenFunction::EmitOpenCLKernelMetadata(const FunctionDecl *FD, llvm::MDNode::get(Context, AttrMDArgs)); } + if (const SYCLIntelMaxWorkGroupSizeAttr *A = + FD->getAttr()) { + llvm::LLVMContext &Context = getLLVMContext(); + Optional XDimVal = + A->getXDim()->getIntegerConstantExpr(FD->getASTContext()); + Optional YDimVal = + A->getYDim()->getIntegerConstantExpr(FD->getASTContext()); + Optional ZDimVal = + A->getZDim()->getIntegerConstantExpr(FD->getASTContext()); + llvm::Metadata *AttrMDArgs[] = { + llvm::ConstantAsMetadata::get( + Builder.getInt32(XDimVal->getZExtValue())), + llvm::ConstantAsMetadata::get( + Builder.getInt32(YDimVal->getZExtValue())), + llvm::ConstantAsMetadata::get( + Builder.getInt32(ZDimVal->getZExtValue()))}; + Fn->setMetadata("max_work_group_size", + llvm::MDNode::get(Context, AttrMDArgs)); + } + if (const SYCLIntelNoGlobalWorkOffsetAttr *A = FD->getAttr()) { const Expr *Arg = A->getValue(); diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index fa60af770bba1..8a931f40ce153 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -8097,16 +8097,22 @@ void TCETargetCodeGenInfo::setTargetAttributes( SmallVector Operands; Operands.push_back(llvm::ConstantAsMetadata::get(F)); - - Operands.push_back( - llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue( - M.Int32Ty, llvm::APInt(32, Attr->getXDim())))); - Operands.push_back( - llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue( - M.Int32Ty, llvm::APInt(32, Attr->getYDim())))); - Operands.push_back( - llvm::ConstantAsMetadata::get(llvm::Constant::getIntegerValue( - M.Int32Ty, llvm::APInt(32, Attr->getZDim())))); + unsigned XDim = Attr->getXDim() + ->EvaluateKnownConstInt(M.getContext()) + .getZExtValue(); + unsigned YDim = Attr->getYDim() + ->EvaluateKnownConstInt(M.getContext()) + .getZExtValue(); + unsigned ZDim = Attr->getZDim() + ->EvaluateKnownConstInt(M.getContext()) + .getZExtValue(); + + Operands.push_back(llvm::ConstantAsMetadata::get( + llvm::Constant::getIntegerValue(M.Int32Ty, llvm::APInt(32, XDim)))); + Operands.push_back(llvm::ConstantAsMetadata::get( + llvm::Constant::getIntegerValue(M.Int32Ty, llvm::APInt(32, YDim)))); + Operands.push_back(llvm::ConstantAsMetadata::get( + llvm::Constant::getIntegerValue(M.Int32Ty, llvm::APInt(32, ZDim)))); // Add a boolean constant operand for "required" (true) or "hint" // (false) for implementing the work_group_size_hint attr later. @@ -8986,6 +8992,9 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes( if (ReqdWGS || FlatWGS) { unsigned Min = 0; unsigned Max = 0; + unsigned XDim = 0; + unsigned YDim = 0; + unsigned ZDim = 0; if (FlatWGS) { Min = FlatWGS->getMin() ->EvaluateKnownConstInt(M.getContext()) @@ -8994,8 +9003,19 @@ void AMDGPUTargetCodeGenInfo::setTargetAttributes( ->EvaluateKnownConstInt(M.getContext()) .getExtValue(); } + if (ReqdWGS) { + XDim = ReqdWGS->getXDim() + ->EvaluateKnownConstInt(M.getContext()) + .getZExtValue(); + YDim = ReqdWGS->getYDim() + ->EvaluateKnownConstInt(M.getContext()) + .getZExtValue(); + ZDim = ReqdWGS->getZDim() + ->EvaluateKnownConstInt(M.getContext()) + .getZExtValue(); + } if (ReqdWGS && Min == 0 && Max == 0) - Min = Max = ReqdWGS->getXDim() * ReqdWGS->getYDim() * ReqdWGS->getZDim(); + Min = Max = XDim * YDim * ZDim; if (Min != 0) { assert(Min <= Max && "Min must be less than or equal Max"); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6bfe4fb67a0df..22283b92a83c8 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -3207,9 +3207,18 @@ static void checkDimensionsAndSetDiagnostics(Sema &S, FunctionDecl *New, if (!NewDeclAttr || !OldDeclAttr) return; - if ((NewDeclAttr->getXDim() != OldDeclAttr->getXDim()) || - (NewDeclAttr->getYDim() != OldDeclAttr->getYDim()) || - (NewDeclAttr->getZDim() != OldDeclAttr->getZDim())) { + /// Returns the usigned constant integer value represented by + /// given expression. + auto getExprValue = [](const Expr *E, ASTContext &Ctx) { + return E->getIntegerConstantExpr(Ctx)->getZExtValue(); + }; + + if ((getExprValue(NewDeclAttr->getXDim(), S.getASTContext()) != + getExprValue(OldDeclAttr->getXDim(), S.getASTContext())) || + (getExprValue(NewDeclAttr->getYDim(), S.getASTContext()) != + getExprValue(OldDeclAttr->getYDim(), S.getASTContext())) || + (getExprValue(NewDeclAttr->getZDim(), S.getASTContext()) != + getExprValue(OldDeclAttr->getZDim(), S.getASTContext()))) { S.Diag(New->getLocation(), diag::err_conflicting_sycl_function_attributes) << OldDeclAttr << NewDeclAttr; S.Diag(New->getLocation(), diag::warn_duplicate_attribute) << OldDeclAttr; diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp index e0c04d239ed88..b8584ef9dc1cf 100644 --- a/clang/lib/Sema/SemaDeclAttr.cpp +++ b/clang/lib/Sema/SemaDeclAttr.cpp @@ -2937,84 +2937,249 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) { // In case the value of 'max_global_work_dim' attribute equals to 0 we shall // ensure that if max_work_group_size and reqd_work_group_size attributes exist, // they hold equal values (1, 1, 1). -static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &Attr, +static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL, uint32_t WGSize[3]) { bool Result = true; - auto checkZeroDim = [&S, &Attr](auto &A, size_t X, size_t Y, size_t Z, - bool ReverseAttrs = false) -> bool { + auto checkZeroDim = [&S, &AL](auto &A, size_t X, size_t Y, size_t Z, + bool ReverseAttrs = false) -> bool { if (X != 1 || Y != 1 || Z != 1) { auto Diag = - S.Diag(Attr.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one); + S.Diag(AL.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one); if (ReverseAttrs) - Diag << Attr << A; + Diag << AL << A; else - Diag << A << Attr; + Diag << A << AL; return false; } return true; }; - if (Attr.getKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) { - if (const auto *A = D->getAttr()) - Result &= checkZeroDim(A, A->getXDim(), A->getYDim(), A->getZDim()); - if (const auto *A = D->getAttr()) - Result &= checkZeroDim(A, A->getXDim(), A->getYDim(), A->getZDim()); + /// Returns the usigned constant integer value represented by + /// given expression. + auto getExprValue = [](const Expr *E, ASTContext &Ctx) { + return E->getIntegerConstantExpr(Ctx)->getZExtValue(); + }; + + if (AL.getKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) { + ArrayRef Dims; + Attr *B = nullptr; + if (const auto *B = D->getAttr()) + Dims = B->dimensions(); + else if (const auto *B = D->getAttr()) + Dims = B->dimensions(); + if (B) { + Result &= checkZeroDim(B, getExprValue(Dims[0], S.getASTContext()), + getExprValue(Dims[1], S.getASTContext()), + getExprValue(Dims[2], S.getASTContext())); + } return Result; } + if (AL.getKind() == ParsedAttr::AT_SYCLIntelMaxWorkGroupSize && + checkDeprecatedSYCLAttributeSpelling(S, AL)) + S.Diag(AL.getLoc(), diag::note_spelling_suggestion) + << "'intel::max_work_group_size'"; + + // For a SYCLDevice, WorkGroupAttr arguments are reversed. + // "XDim" gets the third argument to the attribute and + // "ZDim" gets the first argument of the attribute. if (const auto *A = D->getAttr()) { int64_t AttrValue = A->getValue()->getIntegerConstantExpr(S.Context)->getSExtValue(); - if (AttrValue == 0) - Result &= checkZeroDim(A, WGSize[0], WGSize[1], WGSize[2], - /*ReverseAttrs=*/true); + if (AttrValue == 0) { + Result &= + checkZeroDim(A, getExprValue(AL.getArgAsExpr(2), S.getASTContext()), + getExprValue(AL.getArgAsExpr(1), S.getASTContext()), + getExprValue(AL.getArgAsExpr(0), S.getASTContext()), + /*ReverseAttrs=*/true); + } } if (const auto *A = D->getAttr()) { - if (!(WGSize[0] <= A->getXDim() && WGSize[1] <= A->getYDim() && - WGSize[2] <= A->getZDim())) { - S.Diag(Attr.getLoc(), diag::err_conflicting_sycl_function_attributes) - << Attr << A->getSpelling(); + if (!((getExprValue(AL.getArgAsExpr(2), S.getASTContext()) <= + getExprValue(A->getXDim(), S.getASTContext())) && + (getExprValue(AL.getArgAsExpr(1), S.getASTContext()) <= + getExprValue(A->getYDim(), S.getASTContext())) && + (getExprValue(AL.getArgAsExpr(0), S.getASTContext()) <= + getExprValue(A->getZDim(), S.getASTContext())))) { + S.Diag(AL.getLoc(), diag::err_conflicting_sycl_function_attributes) + << AL << A->getSpelling(); Result &= false; } } - if (Attr.getKind() == ParsedAttr::AT_SYCLIntelMaxWorkGroupSize && - checkDeprecatedSYCLAttributeSpelling(S, Attr)) - S.Diag(Attr.getLoc(), diag::note_spelling_suggestion) - << "'intel::max_work_group_size'"; - if (const auto *A = D->getAttr()) { - if (!(WGSize[0] >= A->getXDim() && WGSize[1] >= A->getYDim() && - WGSize[2] >= A->getZDim())) { - S.Diag(Attr.getLoc(), diag::err_conflicting_sycl_function_attributes) - << Attr << A->getSpelling(); + if (!((getExprValue(AL.getArgAsExpr(2), S.getASTContext()) >= + getExprValue(A->getXDim(), S.getASTContext())) && + (getExprValue(AL.getArgAsExpr(1), S.getASTContext()) >= + getExprValue(A->getYDim(), S.getASTContext())) && + (getExprValue(AL.getArgAsExpr(0), S.getASTContext()) >= + getExprValue(A->getZDim(), S.getASTContext())))) { + S.Diag(AL.getLoc(), diag::err_conflicting_sycl_function_attributes) + << AL << A->getSpelling(); Result &= false; } } return Result; } -// Handles reqd_work_group_size, work_group_size_hint and max_work_group_size +template +static bool handleMaxWorkSizeAttrExpr(Sema &S, const AttrInfo &AI, + const Expr *Expr, unsigned &Val, + unsigned Idx) { + assert(Expr && "Attribute must have an argument."); + + if (!Expr->isInstantiationDependent()) { + Optional ArgVal = + Expr->getIntegerConstantExpr(S.getASTContext()); + + if (!ArgVal) { + S.Diag(getAttrLoc(AI), diag::err_attribute_argument_type) + << &AI << AANT_ArgumentIntegerConstant << Expr->getSourceRange(); + return false; + } + + if (ArgVal->isNegative()) { + S.Diag(Expr->getExprLoc(), + diag::warn_attribute_requires_non_negative_integer_argument) + << &AI << Idx << Expr->getSourceRange(); + return true; + } + + Val = ArgVal->getZExtValue(); + if (Val == 0) { + S.Diag(Expr->getExprLoc(), diag::err_attribute_argument_is_zero) + << &AI << Expr->getSourceRange(); + return false; + } + } + return true; +} + +template +static bool checkMaxWorkSizeAttrArguments(Sema &S, Expr *XDimExpr, + Expr *YDimExpr, Expr *ZDimExpr, + const AttrType &Attr) { + // Accept template arguments for now as they depend on something else. + // We'll get to check them when they eventually get instantiated. + if (XDimExpr->isValueDependent() || + (YDimExpr && YDimExpr->isValueDependent()) || + (ZDimExpr && ZDimExpr->isValueDependent())) + return false; + + unsigned XDim = 0; + if (!handleMaxWorkSizeAttrExpr(S, Attr, XDimExpr, XDim, 0)) + return true; + + unsigned YDim = 0; + if (YDimExpr && !handleMaxWorkSizeAttrExpr(S, Attr, YDimExpr, YDim, 1)) + return true; + + unsigned ZDim = 0; + if (ZDimExpr && !handleMaxWorkSizeAttrExpr(S, Attr, ZDimExpr, ZDim, 2)) + return true; + + return false; +} + +template +void Sema::addIntelSYCLTripleArgFunctionAttr(Decl *D, + const AttributeCommonInfo &CI, + Expr *XDimExpr, Expr *YDimExpr, + Expr *ZDimExpr) { + WorkGroupAttrType TmpAttr(Context, CI, XDimExpr, YDimExpr, ZDimExpr); + + if (checkMaxWorkSizeAttrArguments(*this, XDimExpr, YDimExpr, ZDimExpr, + TmpAttr)) + return; + + D->addAttr(::new (Context) + WorkGroupAttrType(Context, CI, XDimExpr, YDimExpr, ZDimExpr)); +} + +// Handles reqd_work_group_size and max_work_group_size. template static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { if (D->isInvalidDecl()) return; uint32_t WGSize[3]; - if (AL.getKind() == ParsedAttr::AT_ReqdWorkGroupSize && - AL.getAttributeSpellingListIndex() == - ReqdWorkGroupSizeAttr::CXX11_intel_reqd_work_group_size) { - WGSize[1] = ReqdWorkGroupSizeAttr::DefaultYDim; - WGSize[2] = ReqdWorkGroupSizeAttr::DefaultZDim; - } else if (!checkAttributeNumArgs(S, AL, 3)) + + Expr *XDimExpr = AL.getArgAsExpr(0); + + // If no attribute argument is specified, set to default value '1' + // for second and third attribute argument in ReqdWorkGroupSizeAttr + // for only with intel::reqd_work_group_size spelling. + auto SetDefaultValue = [](Sema &S, const ParsedAttr &AL, SourceLocation loc) { + Expr *E = (AL.getKind() == ParsedAttr::AT_ReqdWorkGroupSize && + AL.getAttributeSpellingListIndex() == + ReqdWorkGroupSizeAttr::CXX11_intel_reqd_work_group_size) + ? IntegerLiteral::Create(S.Context, llvm::APInt(32, 1), + S.Context.IntTy, AL.getLoc()) + : nullptr; + return E; + }; + + Expr *YDimExpr = AL.isArgExpr(1) ? AL.getArgAsExpr(1) + : SetDefaultValue(S, AL, AL.getLoc()); + + Expr *ZDimExpr = AL.isArgExpr(2) ? AL.getArgAsExpr(2) + : SetDefaultValue(S, AL, AL.getLoc()); + + if ((AL.getKind() == ParsedAttr::AT_ReqdWorkGroupSize && + AL.getAttributeSpellingListIndex() == + ReqdWorkGroupSizeAttr::CXX11_cl_reqd_work_group_size) || + (AL.getKind() == ParsedAttr::AT_SYCLIntelMaxWorkGroupSize)) { + if (!checkAttributeNumArgs(S, AL, 3)) + return; + } + + // For a SYCLDevice WorkGroupAttr arguments are reversed. + if (S.getLangOpts().SYCLIsDevice) + std::swap(XDimExpr, ZDimExpr); + + if (WorkGroupAttr *ExistingAttr = D->getAttr()) { + Optional XDimVal = + XDimExpr->getIntegerConstantExpr(S.getASTContext()); + Optional YDimVal = + YDimExpr->getIntegerConstantExpr(S.getASTContext()); + Optional ZDimVal = + ZDimExpr->getIntegerConstantExpr(S.getASTContext()); + Optional ExistingXDimVal = + ExistingAttr->getXDim()->getIntegerConstantExpr(S.getASTContext()); + Optional ExistingYDimVal = + ExistingAttr->getYDim()->getIntegerConstantExpr(S.getASTContext()); + Optional ExistingZDimVal = + ExistingAttr->getZDim()->getIntegerConstantExpr(S.getASTContext()); + + // Compare attribute arguments value and warn for a mismatch. + if (!((ExistingXDimVal->getZExtValue() == XDimVal->getZExtValue()) && + (ExistingYDimVal->getZExtValue() == YDimVal->getZExtValue()) && + (ExistingZDimVal->getZExtValue() == ZDimVal->getZExtValue()))) { + S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; + S.Diag(ExistingAttr->getLocation(), diag::note_conflicting_attribute); + } + } + + if (!checkWorkGroupSizeValues(S, D, AL, WGSize)) + return; + + S.addIntelSYCLTripleArgFunctionAttr(D, AL, XDimExpr, YDimExpr, + ZDimExpr); +} + +// Handles work_group_size_hint. +static void handleWorkGroupSizeHint(Sema &S, Decl *D, const ParsedAttr &AL) { + uint32_t WGSize[3]; + + if (!checkAttributeNumArgs(S, AL, 3)) return; for (unsigned i = 0; i < 3; ++i) { - if (i < AL.getNumArgs() && - !checkUInt32Argument(S, AL, AL.getArgAsExpr(i), WGSize[i], i, + if (!checkUInt32Argument(S, AL, AL.getArgAsExpr(i), WGSize[i], i, /*StrictlyUnsigned=*/true)) return; + if (WGSize[i] == 0) { S.Diag(AL.getLoc(), diag::err_attribute_argument_is_zero) << AL << AL.getArgAsExpr(i)->getSourceRange(); @@ -3022,20 +3187,14 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) { } } - // For a SYCLDevice WorkGroupAttr arguments are reversed - if (S.getLangOpts().SYCLIsDevice) { - std::swap(WGSize[0], WGSize[2]); - } - WorkGroupAttr *Existing = D->getAttr(); + WorkGroupSizeHintAttr *Existing = D->getAttr(); if (Existing && !(Existing->getXDim() == WGSize[0] && Existing->getYDim() == WGSize[1] && Existing->getZDim() == WGSize[2])) S.Diag(AL.getLoc(), diag::warn_duplicate_attribute) << AL; - if (!checkWorkGroupSizeValues(S, D, AL, WGSize)) - return; - D->addAttr(::new (S.Context) - WorkGroupAttr(S.Context, AL, WGSize[0], WGSize[1], WGSize[2])); + D->addAttr(::new (S.Context) WorkGroupSizeHintAttr(S.Context, AL, WGSize[0], + WGSize[1], WGSize[2])); } // Handles intel_reqd_sub_group_size. @@ -8473,7 +8632,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, handleXReturnsXRetainedAttr(S, D, AL); break; case ParsedAttr::AT_WorkGroupSizeHint: - handleWorkGroupSize(S, D, AL); + handleWorkGroupSizeHint(S, D, AL); break; case ParsedAttr::AT_ReqdWorkGroupSize: handleWorkGroupSize(S, D, AL); diff --git a/clang/lib/Sema/SemaSYCL.cpp b/clang/lib/Sema/SemaSYCL.cpp index 9ad45432935e1..57208daaf2c64 100644 --- a/clang/lib/Sema/SemaSYCL.cpp +++ b/clang/lib/Sema/SemaSYCL.cpp @@ -3283,9 +3283,12 @@ void Sema::MarkDevice(void) { case attr::Kind::ReqdWorkGroupSize: { auto *Attr = cast(A); if (auto *Existing = SYCLKernel->getAttr()) { - if (Existing->getXDim() != Attr->getXDim() || - Existing->getYDim() != Attr->getYDim() || - Existing->getZDim() != Attr->getZDim()) { + if ((getIntExprValue(Existing->getXDim(), getASTContext()) != + getIntExprValue(Attr->getXDim(), getASTContext())) || + (getIntExprValue(Existing->getYDim(), getASTContext()) != + getIntExprValue(Attr->getYDim(), getASTContext())) || + (getIntExprValue(Existing->getZDim(), getASTContext()) != + getIntExprValue(Attr->getZDim(), getASTContext()))) { Diag(SYCLKernel->getLocation(), diag::err_conflicting_sycl_kernel_attributes); Diag(Existing->getLocation(), diag::note_conflicting_attribute); @@ -3294,9 +3297,12 @@ void Sema::MarkDevice(void) { } } else if (auto *Existing = SYCLKernel->getAttr()) { - if (Existing->getXDim() < Attr->getXDim() || - Existing->getYDim() < Attr->getYDim() || - Existing->getZDim() < Attr->getZDim()) { + if ((getIntExprValue(Existing->getXDim(), getASTContext()) < + getIntExprValue(Attr->getXDim(), getASTContext())) || + (getIntExprValue(Existing->getYDim(), getASTContext()) < + getIntExprValue(Attr->getYDim(), getASTContext())) || + (getIntExprValue(Existing->getZDim(), getASTContext()) < + getIntExprValue(Attr->getZDim(), getASTContext()))) { Diag(SYCLKernel->getLocation(), diag::err_conflicting_sycl_kernel_attributes); Diag(Existing->getLocation(), diag::note_conflicting_attribute); @@ -3313,9 +3319,12 @@ void Sema::MarkDevice(void) { case attr::Kind::SYCLIntelMaxWorkGroupSize: { auto *Attr = cast(A); if (auto *Existing = SYCLKernel->getAttr()) { - if (Existing->getXDim() > Attr->getXDim() || - Existing->getYDim() > Attr->getYDim() || - Existing->getZDim() > Attr->getZDim()) { + if ((getIntExprValue(Existing->getXDim(), getASTContext()) > + getIntExprValue(Attr->getXDim(), getASTContext())) || + (getIntExprValue(Existing->getYDim(), getASTContext()) > + getIntExprValue(Attr->getYDim(), getASTContext())) || + (getIntExprValue(Existing->getZDim(), getASTContext()) > + getIntExprValue(Attr->getZDim(), getASTContext()))) { Diag(SYCLKernel->getLocation(), diag::err_conflicting_sycl_kernel_attributes); Diag(Existing->getLocation(), diag::note_conflicting_attribute); diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp index 5b30b526d97d6..41646b5af17e0 100644 --- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp +++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp @@ -549,6 +549,32 @@ static void instantiateDependentAMDGPUWavesPerEUAttr( S.addAMDGPUWavesPerEUAttr(New, Attr, MinExpr, MaxExpr); } +template +static void instantiateIntelSYCTripleLFunctionAttr( + Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, + const AttrName *Attr, Decl *New) { + EnterExpressionEvaluationContext Unevaluated( + S, Sema::ExpressionEvaluationContext::ConstantEvaluated); + + ExprResult Result = S.SubstExpr(Attr->getXDim(), TemplateArgs); + if (Result.isInvalid()) + return; + Expr *XDimExpr = Result.getAs(); + + Result = S.SubstExpr(Attr->getYDim(), TemplateArgs); + if (Result.isInvalid()) + return; + Expr *YDimExpr = Result.getAs(); + + Result = S.SubstExpr(Attr->getZDim(), TemplateArgs); + if (Result.isInvalid()) + return; + Expr *ZDimExpr = Result.getAs(); + + S.addIntelSYCLTripleArgFunctionAttr(New, *Attr, XDimExpr, YDimExpr, + ZDimExpr); +} + template static void instantiateIntelFPGAMemoryAttr( Sema &S, const MultiLevelTemplateArgumentList &TemplateArgs, @@ -812,6 +838,18 @@ void Sema::InstantiateAttrs(const MultiLevelTemplateArgumentList &TemplateArgs, *this, TemplateArgs, SYCLIntelNoGlobalWorkOffset, New); continue; } + if (const auto *ReqdWorkGroupSize = + dyn_cast(TmplAttr)) { + instantiateIntelSYCTripleLFunctionAttr( + *this, TemplateArgs, ReqdWorkGroupSize, New); + continue; + } + if (const auto *SYCLIntelMaxWorkGroupSize = + dyn_cast(TmplAttr)) { + instantiateIntelSYCTripleLFunctionAttr( + *this, TemplateArgs, SYCLIntelMaxWorkGroupSize, New); + continue; + } // Existing DLL attribute on the instantiation takes precedence. if (TmplAttr->getKind() == attr::DLLExport || TmplAttr->getKind() == attr::DLLImport) { diff --git a/clang/test/CodeGenSYCL/intel-max-work-group-size.cpp b/clang/test/CodeGenSYCL/intel-max-work-group-size.cpp index 87117c585e0d1..3d6a1a85b186c 100644 --- a/clang/test/CodeGenSYCL/intel-max-work-group-size.cpp +++ b/clang/test/CodeGenSYCL/intel-max-work-group-size.cpp @@ -1,24 +1,47 @@ -// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s + +#include "sycl.hpp" + +using namespace cl::sycl; +queue q; class Foo { public: [[intel::max_work_group_size(1, 1, 1)]] void operator()() const {} }; -template -__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) { - kernelFunc(); -} +template +class Functor { +public: + [[intel::max_work_group_size(SIZE, SIZE1, SIZE2)]] void operator()() const {} +}; + +template +[[intel::max_work_group_size(N, N1, N2)]] void func() {} + +int main() { + q.submit([&](handler &h) { + Foo boo; + h.single_task(boo); + + h.single_task( + []() [[intel::max_work_group_size(8, 8, 8)]]{}); -void bar() { - Foo boo; - kernel(boo); + Functor<2, 2, 2> f; + h.single_task(f); - kernel( - []() [[intel::max_work_group_size(8, 8, 8)]]{}); + h.single_task([]() { + func<4, 4, 4>(); + }); + }); + return 0; } -// CHECK: define spir_kernel void @{{.*}}kernel_name1() {{.*}} !max_work_group_size ![[NUM1:[0-9]+]] -// CHECK: define spir_kernel void @{{.*}}kernel_name2() {{.*}} !max_work_group_size ![[NUM8:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name1"() #0 {{.*}} !max_work_group_size ![[NUM1:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name2"() #0 {{.*}} !max_work_group_size ![[NUM8:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name3"() #0 {{.*}} !max_work_group_size ![[NUM2:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name4"() #0 {{.*}} !max_work_group_size ![[NUM4:[0-9]+]] // CHECK: ![[NUM1]] = !{i32 1, i32 1, i32 1} // CHECK: ![[NUM8]] = !{i32 8, i32 8, i32 8} +// CHECK: ![[NUM2]] = !{i32 2, i32 2, i32 2} +// CHECK: ![[NUM4]] = !{i32 4, i32 4, i32 4} diff --git a/clang/test/CodeGenSYCL/reqd-work-group-size.cpp b/clang/test/CodeGenSYCL/reqd-work-group-size.cpp index 72ba3492d2ed0..5ef0ad78108dc 100644 --- a/clang/test/CodeGenSYCL/reqd-work-group-size.cpp +++ b/clang/test/CodeGenSYCL/reqd-work-group-size.cpp @@ -1,4 +1,9 @@ -// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s + +#include "sycl.hpp" + +using namespace cl::sycl; +queue q; class Functor32x16x16 { public: @@ -14,25 +19,43 @@ class Functor { } }; -template -__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) { - kernelFunc(); -} +template +class FunctorTemp { +public: + [[cl::reqd_work_group_size(SIZE, SIZE1, SIZE2)]] void operator()() const {} +}; + +template +[[cl::reqd_work_group_size(N, N1, N2)]] void func() {} + +int main() { + q.submit([&](handler &h) { + Functor32x16x16 f32x16x16; + h.single_task(f32x16x16); + + Functor f; + h.single_task(f); -void bar() { - Functor32x16x16 f32x16x16; - kernel(f32x16x16); + h.single_task( + []() [[cl::reqd_work_group_size(8, 8, 8)]]{}); - Functor f; - kernel(f); + FunctorTemp<2, 2, 2> ft; + h.single_task(ft); - kernel( - []() [[cl::reqd_work_group_size(8, 8, 8)]]{}); + h.single_task([]() { + func<8, 4, 4>(); + }); + }); + return 0; } -// CHECK: define spir_kernel void @{{.*}}kernel_name1() {{.*}} !reqd_work_group_size ![[WGSIZE32:[0-9]+]] -// CHECK: define spir_kernel void @{{.*}}kernel_name2() {{.*}} !reqd_work_group_size ![[WGSIZE8:[0-9]+]] -// CHECK: define spir_kernel void @{{.*}}kernel_name3() {{.*}} !reqd_work_group_size ![[WGSIZE88:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name1"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE32:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name2"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE8:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name3"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE88:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name4"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE22:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name5"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE44:[0-9]+]] // CHECK: ![[WGSIZE32]] = !{i32 16, i32 16, i32 32} // CHECK: ![[WGSIZE8]] = !{i32 1, i32 1, i32 8} // CHECK: ![[WGSIZE88]] = !{i32 8, i32 8, i32 8} +// CHECK: ![[WGSIZE22]] = !{i32 2, i32 2, i32 2} +// CHECK: ![[WGSIZE44]] = !{i32 4, i32 4, i32 8} diff --git a/clang/test/CodeGenSYCL/sycl-multi-kernel-attr.cpp b/clang/test/CodeGenSYCL/sycl-multi-kernel-attr.cpp index 486975a4081ba..7fb26c1a8c09d 100644 --- a/clang/test/CodeGenSYCL/sycl-multi-kernel-attr.cpp +++ b/clang/test/CodeGenSYCL/sycl-multi-kernel-attr.cpp @@ -1,20 +1,54 @@ -// RUN: %clang_cc1 -fsycl -fsycl-is-device -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s +// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -triple spir64-unknown-unknown-sycldevice -disable-llvm-passes -emit-llvm -o - %s | FileCheck %s + +#include "sycl.hpp" + +using namespace cl::sycl; +queue q; class Functor { public: [[intel::reqd_sub_group_size(4), cl::reqd_work_group_size(32, 16, 16)]] void operator()() const {} }; -template -__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) { - kernelFunc(); -} +class Functor1 { +public: + [[intel::reqd_sub_group_size(2), intel::reqd_work_group_size(64, 32, 32)]] void operator()() const {} +}; + +template +class Functor2 { +public: + [[intel::reqd_work_group_size(SIZE, SIZE1, SIZE2)]] void operator()() const {} +}; + +template +[[intel::reqd_work_group_size(N, N1, N2)]] void func() {} + +int main() { + q.submit([&](handler &h) { + Functor foo; + h.single_task(foo); + + Functor1 foo1; + h.single_task(foo1); + + Functor2<2, 2, 2> foo2; + h.single_task(foo2); -void bar() { - Functor foo; - kernel(foo); + h.single_task([]() { + func<8, 4, 4>(); + }); + }); + return 0; } -// CHECK: define spir_kernel void @{{.*}}kernel_name() {{.*}} !reqd_work_group_size ![[WGSIZE:[0-9]+]] !intel_reqd_sub_group_size ![[SGSIZE:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name1"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE:[0-9]+]] !intel_reqd_sub_group_size ![[SGSIZE:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name2"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE1:[0-9]+]] !intel_reqd_sub_group_size ![[SGSIZE1:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name3"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE2:[0-9]+]] +// CHECK: define spir_kernel void @{{.*}}kernel_name4"() #0 {{.*}} !reqd_work_group_size ![[WGSIZE3:[0-9]+]] // CHECK: ![[WGSIZE]] = !{i32 16, i32 16, i32 32} // CHECK: ![[SGSIZE]] = !{i32 4} +// CHECK: ![[WGSIZE1]] = !{i32 32, i32 32, i32 64} +// CHECK: ![[SGSIZE1]] = !{i32 2} +// CHECK: ![[WGSIZE2]] = !{i32 2, i32 2, i32 2} +// CHECK: ![[WGSIZE3]] = !{i32 4, i32 4, i32 8} diff --git a/clang/test/SemaOpenCL/invalid-kernel-attrs.cl b/clang/test/SemaOpenCL/invalid-kernel-attrs.cl index cc68fe41e5416..fef0d59e4b656 100644 --- a/clang/test/SemaOpenCL/invalid-kernel-attrs.cl +++ b/clang/test/SemaOpenCL/invalid-kernel-attrs.cl @@ -42,7 +42,7 @@ kernel __attribute__((intel_reqd_sub_group_size(-1))) void kernel16() {} // expe kernel __attribute__((intel_reqd_sub_group_size(8))) __attribute__((intel_reqd_sub_group_size(16))) void kernel17() {} //expected-warning{{attribute 'intel_reqd_sub_group_size' is already applied with different parameters}} __kernel __attribute__((work_group_size_hint(8,-16,32))) void neg1() {} //expected-error{{'work_group_size_hint' attribute requires a non-negative integral compile time constant expression}} -__kernel __attribute__((reqd_work_group_size(8,16,-32))) void neg2(){} // expected-error{{'reqd_work_group_size' attribute requires a non-negative integral compile time constant expression}} +__kernel __attribute__((reqd_work_group_size(8, 16, -32))) void neg2() {} //expected-warning{{the resulting value of the 'reqd_work_group_size' attribute third parameter is always non-negative after implicit conversion}} // 4294967294 is a negative integer if treated as signed. // Should compile successfully, since we expect an unsigned. diff --git a/clang/test/SemaSYCL/intel-max-global-work-dim-device.cpp b/clang/test/SemaSYCL/intel-max-global-work-dim-device.cpp index 0f28cbd9911e5..cb3e359edd70b 100644 --- a/clang/test/SemaSYCL/intel-max-global-work-dim-device.cpp +++ b/clang/test/SemaSYCL/intel-max-global-work-dim-device.cpp @@ -80,15 +80,27 @@ int main() { h.single_task(TRIFuncObjGood1()); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel4 - // CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 1 - // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} 1 1 1 + // CHECK: ReqdWorkGroupSizeAttr {{.*}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} // CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}} // CHECK-NEXT: IntegerLiteral{{.*}}0{{$}} h.single_task(TRIFuncObjGood2()); // CHECK-LABEL: FunctionDecl {{.*}}test_kernel5 - // CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 4 - // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} 1 1 8 + // CHECK: ReqdWorkGroupSizeAttr {{.*}} + // // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} + // // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} // CHECK: SYCLIntelMaxGlobalWorkDimAttr {{.*}} // CHECK-NEXT: IntegerLiteral{{.*}}3{{$}} #ifdef TRIGGER_ERROR diff --git a/clang/test/SemaSYCL/intel-max-work-group-size-device.cpp b/clang/test/SemaSYCL/intel-max-work-group-size-device.cpp new file mode 100644 index 0000000000000..779b85b10cdaa --- /dev/null +++ b/clang/test/SemaSYCL/intel-max-work-group-size-device.cpp @@ -0,0 +1,102 @@ +// RUN: %clang_cc1 %s -fsyntax-only -fsycl -fsycl-is-device -internal-isystem %S/Inputs -Wno-sycl-2017-compat -triple spir64 -DTRIGGER_ERROR -verify +// RUN: %clang_cc1 %s -fsyntax-only -ast-dump -fsycl -fsycl-is-device -internal-isystem %S/Inputs -Wno-sycl-2017-compat -triple spir64 | FileCheck %s + +#include "sycl.hpp" + +using namespace cl::sycl; +queue q; + +#ifndef __SYCL_DEVICE_ONLY__ +struct FuncObj { + [[intel::max_work_group_size(1, 1, 1)]] // expected-no-diagnostics + void + operator()() const {} +}; + +void foo() { + q.submit([&](handler &h) { + h.single_task(FuncObj()); + }); +} + +#else // __SYCL_DEVICE_ONLY__ + +[[intel::max_work_group_size(2, 2, 2)]] void func_do_not_ignore() {} + +struct FuncObj { + [[intel::max_work_group_size(4, 4, 4)]] void operator()() const {} +}; + +struct Func { + // expected-warning@+2 {{attribute 'intelfpga::max_work_group_size' is deprecated}} + // expected-note@+1 {{did you mean to use 'intel::max_work_group_size' instead?}} + [[intelfpga::max_work_group_size(1, 1, 1)]] void operator()() const {} +}; + +#ifdef TRIGGER_ERROR +struct DAFuncObj { + [[intel::max_work_group_size(4, 4, 4)]] + [[cl::reqd_work_group_size(8, 8, 4)]] // expected-error{{'reqd_work_group_size' attribute conflicts with 'max_work_group_size' attribute}} + void + operator()() const {} +}; +#endif // TRIGGER_ERROR + +int main() { + q.submit([&](handler &h) { + // CHECK-LABEL: FunctionDecl {{.*}}test_kernel1 + // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + h.single_task(FuncObj()); + + // CHECK-LABEL: FunctionDecl {{.*}}test_kernel2 + // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} {{.*}} + // CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + // expected-warning@+3 {{attribute 'intelfpga::max_work_group_size' is deprecated}} + // expected-note@+2 {{did you mean to use 'intel::max_work_group_size' instead?}} + h.single_task( + []() [[intelfpga::max_work_group_size(8, 8, 8)]]{}); + + // CHECK-LABEL: FunctionDecl {{.*}}test_kernel3 + // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} + // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} + h.single_task( + []() { func_do_not_ignore(); }); + + // CHECK-LABEL: FunctionDecl {{.*}}test_kernel4 + // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} + // CHECK-NEXT: UnaryOperator{{.*}} 'int' prefix '-' + // CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} + // expected-warning@+2{{the resulting value of the 'max_work_group_size' attribute first parameter is always non-negative after implicit conversion}} + h.single_task( + []() [[intel::max_work_group_size(8, 8, -8)]]{}); + +#ifdef TRIGGER_ERROR + [[intel::max_work_group_size(1, 1, 1)]] int Var = 0; // expected-error{{'max_work_group_size' attribute only applies to functions}} + + h.single_task( + []() [[intel::max_work_group_size(0, 1, 3)]]{}); // expected-error{{'max_work_group_size' attribute must be greater than 0}} + + h.single_task( + []() [[intel::max_work_group_size(1.2f, 1, 3)]]{}); // expected-error{{'max_work_group_size' attribute requires an integer constant}} + + h.single_task( + []() [[intel::max_work_group_size(16, 16, 16), // expected-note{{conflicting attribute is here}} + intel::max_work_group_size(2, 2, 2)]]{}); // expected-warning{{attribute 'max_work_group_size' is already applied with different parameters}} + + h.single_task( + DAFuncObj()); + +#endif // TRIGGER_ERROR + }); + return 0; +} +#endif // __SYCL_DEVICE_ONLY__ diff --git a/clang/test/SemaSYCL/intel-max-work-group-size-host.cpp b/clang/test/SemaSYCL/intel-max-work-group-size-host.cpp new file mode 100644 index 0000000000000..b8b9ceeafe352 --- /dev/null +++ b/clang/test/SemaSYCL/intel-max-work-group-size-host.cpp @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-host -fsyntax-only -Wno-sycl-2017-compat -verify %s +// expected-no-diagnostics + +[[intel::max_work_group_size(2, 2, 2)]] void func_do_not_ignore() {} + +struct FuncObj { + [[intel::max_work_group_size(4, 4, 4)]] void operator()() const {} +}; diff --git a/clang/test/SemaSYCL/intel-max-work-group-size.cpp b/clang/test/SemaSYCL/intel-max-work-group-size.cpp deleted file mode 100644 index 6a05833815835..0000000000000 --- a/clang/test/SemaSYCL/intel-max-work-group-size.cpp +++ /dev/null @@ -1,86 +0,0 @@ -// RUN: %clang_cc1 %s -fsyntax-only -fsycl -fsycl-is-device -Wno-sycl-2017-compat -triple spir64 -DTRIGGER_ERROR -verify -// RUN: %clang_cc1 %s -fsyntax-only -ast-dump -fsycl -fsycl-is-device -Wno-sycl-2017-compat -triple spir64 | FileCheck %s -// RUN: %clang_cc1 -fsycl -fsycl-is-host -fsyntax-only -Wno-sycl-2017-compat -verify %s - -#ifndef __SYCL_DEVICE_ONLY__ -struct FuncObj { - [[intel::max_work_group_size(1, 1, 1)]] // expected-no-diagnostics - void - operator()() const {} -}; - -template -void kernel(const Func &kernelFunc) { - kernelFunc(); -} - -void foo() { - kernel( - FuncObj()); -} - -#else // __SYCL_DEVICE_ONLY__ - -[[intel::max_work_group_size(2, 2, 2)]] void func_do_not_ignore() {} - -struct FuncObj { - [[intel::max_work_group_size(4, 4, 4)]] void operator()() const {} -}; - -struct Func { - // expected-warning@+2 {{attribute 'intelfpga::max_work_group_size' is deprecated}} - // expected-note@+1 {{did you mean to use 'intel::max_work_group_size' instead?}} - [[intelfpga::max_work_group_size(1, 1, 1)]] void operator()() const {} -}; - -#ifdef TRIGGER_ERROR -struct DAFuncObj { - [[intel::max_work_group_size(4, 4, 4)]] - [[cl::reqd_work_group_size(8, 8, 4)]] // expected-error{{'reqd_work_group_size' attribute conflicts with 'max_work_group_size' attribute}} - void - operator()() const {} -}; -#endif // TRIGGER_ERROR - -template -__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) { - kernelFunc(); -} - -int main() { - // CHECK-LABEL: FunctionDecl {{.*}}test_kernel1 - // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} 4 4 4 - kernel( - FuncObj()); - - // CHECK-LABEL: FunctionDecl {{.*}}test_kernel2 - // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} 8 8 8 - // expected-warning@+3 {{attribute 'intelfpga::max_work_group_size' is deprecated}} - // expected-note@+2 {{did you mean to use 'intel::max_work_group_size' instead?}} - kernel( - []() [[intelfpga::max_work_group_size(8, 8, 8)]]{}); - - // CHECK-LABEL: FunctionDecl {{.*}}test_kernel3 - // CHECK: SYCLIntelMaxWorkGroupSizeAttr {{.*}} - kernel( - []() { func_do_not_ignore(); }); - -#ifdef TRIGGER_ERROR - [[intel::max_work_group_size(1, 1, 1)]] int Var = 0; // expected-error{{'max_work_group_size' attribute only applies to functions}} - - kernel( - []() [[intel::max_work_group_size(0, 1, 3)]]{}); // expected-error{{'max_work_group_size' attribute must be greater than 0}} - - kernel( - []() [[intel::max_work_group_size(-8, 8, 1)]]{}); // expected-error{{'max_work_group_size' attribute requires a non-negative integral compile time constant expression}} - - kernel( - []() [[intel::max_work_group_size(16, 16, 16), - intel::max_work_group_size(2, 2, 2)]]{}); // expected-warning{{attribute 'max_work_group_size' is already applied with different parameters}} - - kernel( - DAFuncObj()); - -#endif // TRIGGER_ERROR -} -#endif // __SYCL_DEVICE_ONLY__ diff --git a/clang/test/SemaSYCL/intel-reqd-work-group-size-device.cpp b/clang/test/SemaSYCL/intel-reqd-work-group-size-device.cpp new file mode 100644 index 0000000000000..5e7e9fe900944 --- /dev/null +++ b/clang/test/SemaSYCL/intel-reqd-work-group-size-device.cpp @@ -0,0 +1,161 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -Wno-sycl-2017-compat -fsyntax-only -verify -DTRIGGER_ERROR %s +// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -Wno-sycl-2017-compat -ast-dump %s | FileCheck %s + +#include "sycl.hpp" + +using namespace cl::sycl; +queue q; + +#ifndef __SYCL_DEVICE_ONLY__ +// expected-no-diagnostics +class Functor { +public: + [[intel::reqd_work_group_size(4)]] void operator()() const {} +}; + +void bar() { + q.submit([&](handler &h) { + Functor f; + h.single_task(f); + }); +} + +#else +[[intel::reqd_work_group_size(4)]] void f4x1x1() {} // expected-note {{conflicting attribute is here}} +// expected-note@-1 {{conflicting attribute is here}} +[[intel::reqd_work_group_size(32)]] void f32x1x1() {} // expected-note {{conflicting attribute is here}} + +[[intel::reqd_work_group_size(16)]] void f16x1x1() {} // expected-note {{conflicting attribute is here}} +[[intel::reqd_work_group_size(16, 16)]] void f16x16x1() {} // expected-note {{conflicting attribute is here}} + +[[intel::reqd_work_group_size(32, 32)]] void f32x32x1() {} // expected-note {{conflicting attribute is here}} +[[intel::reqd_work_group_size(32, 32, 32)]] void f32x32x32() {} // expected-note {{conflicting attribute is here}} + +#ifdef TRIGGER_ERROR +class Functor32 { +public: + [[cl::reqd_work_group_size(32)]] void operator()() const {} // expected-error {{'reqd_work_group_size' attribute requires exactly 3 arguments}} +}; +#endif // TRIGGER_ERROR + +class Functor33 { +public: + // expected-warning@+1{{the resulting value of the 'reqd_work_group_size' attribute second parameter is always non-negative after implicit conversion}} + [[intel::reqd_work_group_size(32, -4)]] void operator()() const {} +}; + +class Functor16 { +public: + [[intel::reqd_work_group_size(16)]] void operator()() const {} +}; + +class Functor64 { +public: + [[intel::reqd_work_group_size(64, 64)]] void operator()() const {} +}; + +class Functor16x16x16 { +public: + [[intel::reqd_work_group_size(16, 16, 16)]] void operator()() const {} +}; + +class Functor8 { // expected-error {{conflicting attributes applied to a SYCL kernel}} +public: + [[intel::reqd_work_group_size(8)]] void operator()() const { // expected-note {{conflicting attribute is here}} + f4x1x1(); + } +}; + +class Functor { +public: + void operator()() const { + f4x1x1(); + } +}; + +class FunctorAttr { +public: + __attribute__((reqd_work_group_size(128, 128, 128))) void operator()() const {} +}; + +int main() { + q.submit([&](handler &h) { + Functor16 f16; + h.single_task(f16); + + Functor f; + h.single_task(f); + + Functor16x16x16 f16x16x16; + h.single_task(f16x16x16); + + FunctorAttr fattr; + h.single_task(fattr); + + Functor33 f33; + h.single_task(f33); + + h.single_task([]() [[intel::reqd_work_group_size(32, 32, 32)]] { + f32x32x32(); + }); +#ifdef TRIGGER_ERROR + Functor8 f8; + h.single_task(f8); + + h.single_task([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} + f4x1x1(); + f32x1x1(); + }); + + h.single_task([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} + f16x1x1(); + f16x16x1(); + }); + + h.single_task([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} + f32x32x32(); + f32x32x1(); + }); + + // expected-error@+1 {{expected variable name or 'this' in lambda capture list}} + h.single_task([[intel::reqd_work_group_size(32, 32, 32)]][]() { + f32x32x32(); + }); + +#endif // TRIGGER_ERROR + }); + return 0; +} + +// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name1 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} +// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name2 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} +// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name3 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} +// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name4 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}128{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}128{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}128{{$}} +// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name5 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: UnaryOperator{{.*}} 'int' prefix '-' +// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}32{{$}} +// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name6 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}32{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}32{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}32{{$}} +#endif // __SYCL_DEVICE_ONLY__ diff --git a/clang/test/SemaSYCL/intel-reqd-work-group-size-host.cpp b/clang/test/SemaSYCL/intel-reqd-work-group-size-host.cpp new file mode 100644 index 0000000000000..d7518762102d4 --- /dev/null +++ b/clang/test/SemaSYCL/intel-reqd-work-group-size-host.cpp @@ -0,0 +1,13 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-host -Wno-sycl-2017-compat -fsyntax-only -verify %s +// expected-no-diagnostics + +[[intel::reqd_work_group_size(4)]] void f4x1x1() {} + +[[intel::reqd_work_group_size(16)]] void f16x1x1() {} + +[[intel::reqd_work_group_size(32, 32, 32)]] void f32x32x32() {} + +class Functor64 { +public: + [[intel::reqd_work_group_size(64, 64, 64)]] void operator()() const {} +}; diff --git a/clang/test/SemaSYCL/intel-reqd-work-group-size.cpp b/clang/test/SemaSYCL/intel-reqd-work-group-size.cpp deleted file mode 100644 index 09fe0934029b2..0000000000000 --- a/clang/test/SemaSYCL/intel-reqd-work-group-size.cpp +++ /dev/null @@ -1,136 +0,0 @@ -// RUN: %clang_cc1 -fsycl -fsycl-is-device -Wno-sycl-2017-compat -fsyntax-only -verify -DTRIGGER_ERROR %s -// RUN: %clang_cc1 -fsycl -fsycl-is-device -Wno-sycl-2017-compat -ast-dump %s | FileCheck %s -// RUN: %clang_cc1 -fsycl -fsycl-is-host -Wno-sycl-2017-compat -fsyntax-only -verify %s - -#ifndef __SYCL_DEVICE_ONLY__ -// expected-no-diagnostics -class Functor { -public: - [[intel::reqd_work_group_size(4)]] void operator()() const {} -}; - -template -void kernel(const Func &kernelFunc) { - kernelFunc(); -} - -void bar() { - Functor f; - kernel(f); -} -#else -[[intel::reqd_work_group_size(4)]] void f4x1x1() {} // expected-note {{conflicting attribute is here}} -// expected-note@-1 {{conflicting attribute is here}} -[[intel::reqd_work_group_size(32)]] void f32x1x1() {} // expected-note {{conflicting attribute is here}} - -[[intel::reqd_work_group_size(16)]] void f16x1x1() {} // expected-note {{conflicting attribute is here}} -[[intel::reqd_work_group_size(16, 16)]] void f16x16x1() {} // expected-note {{conflicting attribute is here}} - -[[intel::reqd_work_group_size(32, 32)]] void f32x32x1() {} // expected-note {{conflicting attribute is here}} -[[intel::reqd_work_group_size(32, 32, 32)]] void f32x32x32() {} // expected-note {{conflicting attribute is here}} - -#ifdef TRIGGER_ERROR -class Functor32 { -public: - [[cl::reqd_work_group_size(32)]] void operator()() const {} // expected-error {{'reqd_work_group_size' attribute requires exactly 3 arguments}} -}; -class Functor33 { -public: - [[intel::reqd_work_group_size(32, -4)]] void operator()() const {} // expected-error {{'reqd_work_group_size' attribute requires a non-negative integral compile time constant expression}} -}; -#endif // TRIGGER_ERROR - -class Functor16 { -public: - [[intel::reqd_work_group_size(16)]] void operator()() const {} -}; - -class Functor64 { -public: - [[intel::reqd_work_group_size(64, 64)]] void operator()() const {} -}; - -class Functor16x16x16 { -public: - [[intel::reqd_work_group_size(16, 16, 16)]] void operator()() const {} -}; - -class Functor8 { // expected-error {{conflicting attributes applied to a SYCL kernel}} -public: - [[intel::reqd_work_group_size(8)]] void operator()() const { // expected-note {{conflicting attribute is here}} - f4x1x1(); - } -}; - -class Functor { -public: - void operator()() const { - f4x1x1(); - } -}; - -class FunctorAttr { -public: - __attribute__((reqd_work_group_size(128, 128, 128))) void operator()() const {} -}; - -template -__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) { - kernelFunc(); -} - -void bar() { - Functor16 f16; - kernel(f16); - - Functor f; - kernel(f); - - Functor16x16x16 f16x16x16; - kernel(f16x16x16); - - FunctorAttr fattr; - kernel(fattr); - - kernel([]() [[intel::reqd_work_group_size(32, 32, 32)]] { - f32x32x32(); - }); - -#ifdef TRIGGER_ERROR - Functor8 f8; - kernel(f8); - - kernel([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} - f4x1x1(); - f32x1x1(); - }); - - kernel([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} - f16x1x1(); - f16x16x1(); - }); - - kernel([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} - f32x32x32(); - f32x32x1(); - }); - - // expected-error@+1 {{expected variable name or 'this' in lambda capture list}} - kernel([[intel::reqd_work_group_size(32, 32, 32)]][]() { - f32x32x32(); - }); - -#endif // TRIGGER_ERROR -} - -// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name1 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 16 -// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name2 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 4 -// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name3 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 16 16 16 -// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name4 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 128 128 128 -// CHECK: FunctionDecl {{.*}} {{.*}}kernel_name5 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 32 32 32 -#endif // __SYCL_DEVICE_ONLY__ diff --git a/clang/test/SemaSYCL/redeclaration-attribute-propagation.cpp b/clang/test/SemaSYCL/redeclaration-attribute-propagation.cpp index 436f9b3186de2..325ed8ad261b0 100644 --- a/clang/test/SemaSYCL/redeclaration-attribute-propagation.cpp +++ b/clang/test/SemaSYCL/redeclaration-attribute-propagation.cpp @@ -53,9 +53,16 @@ int main() { #ifndef TRIGGER_ERROR // CHECK-LABEL: FunctionDecl {{.*}} main 'int ()' // CHECK: `-FunctionDecl {{.*}}test_kernel1 'void ()' - // CHECK: -SYCLIntelMaxWorkGroupSizeAttr {{.*}} Inherited 4 4 4 + // CHECK: -SYCLIntelMaxWorkGroupSizeAttr {{.*}} Inherited + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK: -SYCLIntelNoGlobalWorkOffsetAttr {{.*}} - // CHECK: `-ReqdWorkGroupSizeAttr {{.*}} 2 2 2 + // CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} + // CHECK: `-ReqdWorkGroupSizeAttr {{.*}} + // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} + // CHECK-NEXT: IntegerLiteral{{.*}}2{{$}} h.single_task( []() { func1(); }); diff --git a/clang/test/SemaSYCL/reqd-work-group-size-device.cpp b/clang/test/SemaSYCL/reqd-work-group-size-device.cpp index 65bb0b13474d7..441516a57ded9 100644 --- a/clang/test/SemaSYCL/reqd-work-group-size-device.cpp +++ b/clang/test/SemaSYCL/reqd-work-group-size-device.cpp @@ -1,5 +1,10 @@ -// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -Wno-sycl-2017-compat -verify -DTRIGGER_ERROR %s -// RUN: %clang_cc1 -fsycl -fsycl-is-device -Wno-sycl-2017-compat -ast-dump %s | FileCheck %s +// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -fsyntax-only -Wno-sycl-2017-compat -verify -DTRIGGER_ERROR %s +// RUN: %clang_cc1 -fsycl -fsycl-is-device -internal-isystem %S/Inputs -Wno-sycl-2017-compat -ast-dump %s | FileCheck %s + +#include "sycl.hpp" + +using namespace cl::sycl; +queue q; [[cl::reqd_work_group_size(4, 1, 1)]] void f4x1x1() {} // expected-note {{conflicting attribute is here}} // expected-note@-1 {{conflicting attribute is here}} @@ -19,7 +24,8 @@ class Functor16 { #ifdef TRIGGER_ERROR class Functor32 { public: - //expected-warning@+2{{attribute 'reqd_work_group_size' is already applied with different parameters}} + // expected-note@+3{{conflicting attribute is here}} + // expected-warning@+2{{attribute 'reqd_work_group_size' is already applied with different parameters}} // expected-error@+1{{'reqd_work_group_size' attribute conflicts with 'reqd_work_group_size' attribute}} [[cl::reqd_work_group_size(32, 1, 1)]] [[cl::reqd_work_group_size(1, 1, 32)]] void operator()() const {} }; @@ -48,65 +54,78 @@ class FunctorAttr { __attribute__((reqd_work_group_size(128, 128, 128))) void operator()() const {} }; -template -__attribute__((sycl_kernel)) void kernel(const Func &kernelFunc) { - kernelFunc(); -} - -void bar() { - Functor16 f16; - kernel(f16); +int main() { + q.submit([&](handler &h) { + Functor16 f16; + h.single_task(f16); - Functor f; - kernel(f); + Functor f; + h.single_task(f); - Functor16x16x16 f16x16x16; - kernel(f16x16x16); + Functor16x16x16 f16x16x16; + h.single_task(f16x16x16); - FunctorAttr fattr; - kernel(fattr); + FunctorAttr fattr; + h.single_task(fattr); - kernel([]() [[cl::reqd_work_group_size(32, 32, 32), cl::reqd_work_group_size(32, 32, 32)]] { - f32x32x32(); - }); + h.single_task([]() [[cl::reqd_work_group_size(32, 32, 32), cl::reqd_work_group_size(32, 32, 32)]] { + f32x32x32(); + }); #ifdef TRIGGER_ERROR - Functor8 f8; - kernel(f8); + Functor8 f8; + h.single_task(f8); - Functor32 f32; - kernel(f32); + Functor32 f32; + h.single_task(f32); - kernel([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} - f4x1x1(); - f32x1x1(); - }); + h.single_task([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} + f4x1x1(); + f32x1x1(); + }); - kernel([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} - f16x1x1(); - f16x16x1(); - }); + h.single_task([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} + f16x1x1(); + f16x16x1(); + }); - kernel([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} - f32x32x32(); - f32x32x1(); - }); + h.single_task([]() { // expected-error {{conflicting attributes applied to a SYCL kernel}} + f32x32x32(); + f32x32x1(); + }); - // expected-error@+1 {{expected variable name or 'this' in lambda capture list}} - kernel([[cl::reqd_work_group_size(32, 32, 32)]][]() { - f32x32x32(); - }); + // expected-error@+1 {{expected variable name or 'this' in lambda capture list}} + h.single_task([[cl::reqd_work_group_size(32, 32, 32)]][]() { + f32x32x32(); + }); #endif + }); + return 0; } // CHECK: FunctionDecl {{.*}} {{.*}}kernel_name1 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 16 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} // CHECK: FunctionDecl {{.*}} {{.*}}kernel_name2 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 1 1 4 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} // CHECK: FunctionDecl {{.*}} {{.*}}kernel_name3 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 16 16 16 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} // CHECK: FunctionDecl {{.*}} {{.*}}kernel_name4 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 128 128 128 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}128{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}128{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}128{{$}} // CHECK: FunctionDecl {{.*}} {{.*}}kernel_name5 -// CHECK: ReqdWorkGroupSizeAttr {{.*}} 32 32 32 +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}32{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}32{{$}} +// CHECK-NEXT: IntegerLiteral{{.*}}32{{$}} diff --git a/clang/test/SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp new file mode 100644 index 0000000000000..50cc361c19796 --- /dev/null +++ b/clang/test/SemaSYCL/sycl-device-intel-max-work-group-size-template.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s + +// Test that checks template parameter support for 'max_work_group_size' attribute on sycl device. + +// Test that checks wrong function template instantiation and ensures that the type +// is checked properly when instantiating from the template definition. + +template +// expected-error@+1{{'max_work_group_size' attribute requires an integer constant}} +[[intel::max_work_group_size(Ty{}, Ty1{}, Ty2{})]] void func() {} + +struct S {}; +void var() { + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); +} + +// Test that checks expression is not a constant expression. +int foo(); +// expected-error@+1{{'max_work_group_size' attribute requires an integer constant}} +[[intel::max_work_group_size(foo() + 12, foo() + 12, foo() + 12)]] void func1(); + +// Test that checks expression is a constant expression. +constexpr int bar() { return 0; } +[[intel::max_work_group_size(bar() + 12, bar() + 12, bar() + 12)]] void func2(); // OK + +// Test that checks template parameter suppport on member function of class template. +template +class KernelFunctor { +public: + [[intel::max_work_group_size(SIZE, SIZE1, SIZE2)]] void operator()() {} +}; + +int main() { + KernelFunctor<4, 4, 4>(); +} + +// CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor +// CHECK: ClassTemplateSpecializationDecl {{.*}} {{.*}} class KernelFunctor definition +// CHECK: CXXRecordDecl {{.*}} {{.*}} implicit class KernelFunctor +// SYCLIntelMaxWorkGroupSizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}4{{$}} + +// Test that checks template parameter suppport on function. +template +[[intel::max_work_group_size(N, N1, N2)]] void func3() {} + +int check() { + func3<8, 8, 8>(); + return 0; +} + +// CHECK: FunctionTemplateDecl {{.*}} {{.*}} func3 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 0 N +// CHECK: FunctionDecl {{.*}} {{.*}} func3 'void ()' +// SYCLIntelMaxWorkGroupSizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} diff --git a/clang/test/SemaSYCL/sycl-device-intel-reqd-work-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-intel-reqd-work-group-size-template.cpp new file mode 100644 index 0000000000000..0e00286f9a287 --- /dev/null +++ b/clang/test/SemaSYCL/sycl-device-intel-reqd-work-group-size-template.cpp @@ -0,0 +1,73 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s + +// Test that checks template parameter support for 'intel::reqd_work_group_size' attribute on sycl device. + +// Test that checks wrong function template instantiation and ensures that the type +// is checked properly when instantiating from the template definition. + +template +// expected-error@+1{{'reqd_work_group_size' attribute requires an integer constant}} +[[intel::reqd_work_group_size(Ty{}, Ty1{}, Ty2{})]] void func() {} + +struct S {}; +void var() { + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); +} + +// Test that checks expression is not a constant expression. +int foo(); +// expected-error@+1{{'reqd_work_group_size' attribute requires an integer constant}} +[[intel::reqd_work_group_size(foo() + 12, foo() + 12, foo() + 12)]] void func1(); + +// Test that checks expression is a constant expression. +constexpr int bar() { return 0; } +[[intel::reqd_work_group_size(bar() + 12, bar() + 12, bar() + 12)]] void func2(); // OK + +// Test that checks template parameter suppport on member function of class template. +template +class KernelFunctor { +public: + [[intel::reqd_work_group_size(SIZE, SIZE1, SIZE2)]] void operator()() {} +}; + +int main() { + KernelFunctor<16, 1, 1>(); +} + +// CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor +// CHECK: ClassTemplateSpecializationDecl {{.*}} {{.*}} class KernelFunctor definition +// CHECK: CXXRecordDecl {{.*}} {{.*}} implicit class KernelFunctor +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} + +// Test that checks template parameter suppport on function. +template +[[intel::reqd_work_group_size(N, N1, N2)]] void func3() {} + +int check() { + func3<8, 8, 8>(); + return 0; +} + +// CHECK: FunctionTemplateDecl {{.*}} {{.*}} func3 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 0 N +// CHECK: FunctionDecl {{.*}} {{.*}} func3 'void ()' +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} diff --git a/clang/test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp b/clang/test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp new file mode 100644 index 0000000000000..f46e40933b59f --- /dev/null +++ b/clang/test/SemaSYCL/sycl-device-reqd-work-group-size-template.cpp @@ -0,0 +1,75 @@ +// RUN: %clang_cc1 -fsycl -fsycl-is-device -fsyntax-only -ast-dump -verify -pedantic %s | FileCheck %s + +// Test that checks template parameter support for 'cl::reqd_work_group_size' attribute on sycl device. + +// Test that checks wrong function template instantiation and ensures that the type +// is checked properly when instantiating from the template definition. + +template +// expected-error@+1{{'reqd_work_group_size' attribute requires an integer constant}} +[[cl::reqd_work_group_size(Ty{}, Ty1{}, Ty2{})]] void func() {} + +struct S {}; +void var() { + //expected-note@+1{{in instantiation of function template specialization 'func' requested here}} + func(); +} + +// Test that checks expression is not a constant expression. +int foo(); +// expected-error@+1{{'reqd_work_group_size' attribute requires an integer constant}} +[[cl::reqd_work_group_size(foo() + 12, foo() + 12, foo() + 12)]] void func1(); + +// Test that checks expression is a constant expression. +constexpr int bar() { return 0; } +[[cl::reqd_work_group_size(bar() + 12, bar() + 12, bar() + 12)]] void func2(); // OK + +// Test that checks template parameter suppport on member function of class template. +template +class KernelFunctor { +public: + [[cl::reqd_work_group_size(SIZE, SIZE1, SIZE2)]] void operator()() {} +}; + +int main() { + KernelFunctor<16, 1, 1>(); +} + +// CHECK: ClassTemplateDecl {{.*}} {{.*}} KernelFunctor +// CHECK: ClassTemplateSpecializationDecl {{.*}} {{.*}} class KernelFunctor definition +// CHECK: CXXRecordDecl {{.*}} {{.*}} implicit class KernelFunctor +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}1{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}16{{$}} + +// Test that checks template parameter suppport on function. +template +[[cl::reqd_work_group_size(N, N1, N2)]] void func3() {} + +int check() { + func3<8, 8, 8>(); + return 0; +} + +// CHECK: FunctionTemplateDecl {{.*}} {{.*}} func3 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 0 N +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 1 N1 +// CHECK: NonTypeTemplateParmDecl {{.*}} {{.*}} referenced 'int' depth 0 index 2 N2 +// CHECK: FunctionDecl {{.*}} {{.*}} func3 'void ()' +// CHECK: ReqdWorkGroupSizeAttr {{.*}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}} +// CHECK: SubstNonTypeTemplateParmExpr {{.*}} +// CHECK-NEXT: NonTypeTemplateParmDecl {{.*}} +// CHECK-NEXT: IntegerLiteral{{.*}}8{{$}}