@@ -3268,12 +3268,31 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
32683268
32693269 ASTContext &Ctx = S.getASTContext ();
32703270
3271+ // The arguments to reqd_work_group_size are ordered based on which index
3272+ // increments the fastest. In OpenCL, the first argument is the index that
3273+ // increments the fastest, and in SYCL, the last argument is the index that
3274+ // increments the fastest.
3275+ //
3276+ // [[sycl::reqd_work_group_size]] and [[cl::reqd_work_group_size]] are
3277+ // available in SYCL modes and follow the SYCL rules.
3278+ // __attribute__((reqd_work_group_size)) is only available in OpenCL mode
3279+ // and follows the OpenCL rules.
32713280 if (const auto *A = D->getAttr <SYCLIntelMaxWorkGroupSizeAttr>()) {
3272- if (!((getExprValue (AL.getArgAsExpr (0 ), Ctx) <= *A->getXDimVal ()) &&
3273- (getExprValue (AL.getArgAsExpr (1 ), Ctx) <= *A->getYDimVal ()) &&
3274- (getExprValue (AL.getArgAsExpr (2 ), Ctx) <= *A->getZDimVal ()))) {
3281+ bool CheckFirstArgument =
3282+ S.getLangOpts ().OpenCL
3283+ ? getExprValue (AL.getArgAsExpr (0 ), Ctx) > *A->getZDimVal ()
3284+ : getExprValue (AL.getArgAsExpr (0 ), Ctx) > *A->getXDimVal ();
3285+ bool CheckSecondArgument =
3286+ getExprValue (AL.getArgAsExpr (1 ), Ctx) > *A->getYDimVal ();
3287+ bool CheckThirdArgument =
3288+ S.getLangOpts ().OpenCL
3289+ ? getExprValue (AL.getArgAsExpr (2 ), Ctx) > *A->getXDimVal ()
3290+ : getExprValue (AL.getArgAsExpr (2 ), Ctx) > *A->getZDimVal ();
3291+
3292+ if (CheckFirstArgument || CheckSecondArgument || CheckThirdArgument) {
32753293 S.Diag (AL.getLoc (), diag::err_conflicting_sycl_function_attributes)
3276- << AL << A->getSpelling ();
3294+ << AL << A;
3295+ S.Diag (A->getLocation (), diag::note_conflicting_attribute);
32773296 Result &= false ;
32783297 }
32793298 }
@@ -3286,7 +3305,8 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
32863305 (getExprValue (AL.getArgAsExpr (2 ), Ctx) >=
32873306 getExprValue (A->getZDim (), Ctx)))) {
32883307 S.Diag (AL.getLoc (), diag::err_conflicting_sycl_function_attributes)
3289- << AL << A->getSpelling ();
3308+ << AL << A;
3309+ S.Diag (A->getLocation (), diag::note_conflicting_attribute);
32903310 Result &= false ;
32913311 }
32923312 }
@@ -3562,6 +3582,23 @@ static bool InvalidWorkGroupSizeAttrs(const Expr *MGValue, const Expr *XDim,
35623582 ZDimExpr->getResultAsAPSInt () != 1 ));
35633583}
35643584
3585+ // If the [[intel::max_work_group_size(X, Y, Z)]] attribute is specified on
3586+ // a declaration along with [[sycl::reqd_work_group_size(X1, Y1, Z1)]]
3587+ // attribute, check to see if values of reqd_work_group_size arguments are
3588+ // equal or less than values of max_work_group_size attribute arguments.
3589+ static bool checkWorkGroupSizeAttrValues (const Expr *RWGS, const Expr *MWGS) {
3590+ // If any of the operand is still value dependent, we can't test anything.
3591+ const auto *RWGSCE = dyn_cast<ConstantExpr>(RWGS);
3592+ const auto *MWGSCE = dyn_cast<ConstantExpr>(MWGS);
3593+
3594+ if (!RWGSCE || !MWGSCE)
3595+ return false ;
3596+
3597+ // Otherwise, check if value of reqd_work_group_size argument is
3598+ // greater than value of max_work_group_size attribute argument.
3599+ return RWGSCE->getResultAsAPSInt () > MWGSCE->getResultAsAPSInt ();
3600+ }
3601+
35653602void Sema::AddSYCLIntelMaxWorkGroupSizeAttr (Decl *D,
35663603 const AttributeCommonInfo &CI,
35673604 Expr *XDim, Expr *YDim,
@@ -3595,6 +3632,40 @@ void Sema::AddSYCLIntelMaxWorkGroupSizeAttr(Decl *D,
35953632 if (!XDim || !YDim || !ZDim)
35963633 return ;
35973634
3635+ // If the [[intel::max_work_group_size(X, Y, Z)]] attribute is specified on
3636+ // a declaration along with [[sycl::reqd_work_group_size(X1, Y1, Z1)]]
3637+ // attribute, check to see if values of reqd_work_group_size arguments are
3638+ // equal or less than values of max_work_group_size attribute arguments.
3639+ //
3640+ // The arguments to reqd_work_group_size are ordered based on which index
3641+ // increments the fastest. In OpenCL, the first argument is the index that
3642+ // increments the fastest, and in SYCL, the last argument is the index that
3643+ // increments the fastest.
3644+ //
3645+ // [[sycl::reqd_work_group_size]] and [[cl::reqd_work_group_size]] are
3646+ // available in SYCL modes and follow the SYCL rules.
3647+ // __attribute__((reqd_work_group_size)) is only available in OpenCL mode
3648+ // and follows the OpenCL rules.
3649+ if (const auto *DeclAttr = D->getAttr <ReqdWorkGroupSizeAttr>()) {
3650+ bool CheckFirstArgument =
3651+ getLangOpts ().OpenCL
3652+ ? checkWorkGroupSizeAttrValues (DeclAttr->getXDim (), ZDim)
3653+ : checkWorkGroupSizeAttrValues (DeclAttr->getXDim (), XDim);
3654+ bool CheckSecondArgument =
3655+ checkWorkGroupSizeAttrValues (DeclAttr->getYDim (), YDim);
3656+ bool CheckThirdArgument =
3657+ getLangOpts ().OpenCL
3658+ ? checkWorkGroupSizeAttrValues (DeclAttr->getZDim (), XDim)
3659+ : checkWorkGroupSizeAttrValues (DeclAttr->getZDim (), ZDim);
3660+
3661+ if (CheckFirstArgument || CheckSecondArgument || CheckThirdArgument) {
3662+ Diag (CI.getLoc (), diag::err_conflicting_sycl_function_attributes)
3663+ << CI << DeclAttr;
3664+ Diag (DeclAttr->getLoc (), diag::note_conflicting_attribute);
3665+ return ;
3666+ }
3667+ }
3668+
35983669 // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr, check to see if
35993670 // the attribute holds equal values to (1, 1, 1) in case the value of
36003671 // SYCLIntelMaxGlobalWorkDimAttr equals to 0.
@@ -3655,6 +3726,40 @@ SYCLIntelMaxWorkGroupSizeAttr *Sema::MergeSYCLIntelMaxWorkGroupSizeAttr(
36553726 return nullptr ;
36563727 }
36573728
3729+ // If the [[intel::max_work_group_size(X, Y, Z)]] attribute is specified on
3730+ // a declaration along with [[sycl::reqd_work_group_size(X1, Y1, Z1)]]
3731+ // attribute, check to see if values of reqd_work_group_size arguments are
3732+ // equal or less than values of max_work_group_size attribute arguments.
3733+ //
3734+ // The arguments to reqd_work_group_size are ordered based on which index
3735+ // increments the fastest. In OpenCL, the first argument is the index that
3736+ // increments the fastest, and in SYCL, the last argument is the index that
3737+ // increments the fastest.
3738+ //
3739+ // [[sycl::reqd_work_group_size]] and [[cl::reqd_work_group_size]] are
3740+ // available in SYCL modes and follow the SYCL rules.
3741+ // __attribute__((reqd_work_group_size)) is only available in OpenCL mode
3742+ // and follows the OpenCL rules.
3743+ if (const auto *DeclAttr = D->getAttr <ReqdWorkGroupSizeAttr>()) {
3744+ bool CheckFirstArgument =
3745+ getLangOpts ().OpenCL
3746+ ? checkWorkGroupSizeAttrValues (DeclAttr->getXDim (), A.getZDim ())
3747+ : checkWorkGroupSizeAttrValues (DeclAttr->getXDim (), A.getXDim ());
3748+ bool CheckSecondArgument =
3749+ checkWorkGroupSizeAttrValues (DeclAttr->getYDim (), A.getYDim ());
3750+ bool CheckThirdArgument =
3751+ getLangOpts ().OpenCL
3752+ ? checkWorkGroupSizeAttrValues (DeclAttr->getZDim (), A.getXDim ())
3753+ : checkWorkGroupSizeAttrValues (DeclAttr->getZDim (), A.getZDim ());
3754+
3755+ if (CheckFirstArgument || CheckSecondArgument || CheckThirdArgument) {
3756+ Diag (DeclAttr->getLoc (), diag::err_conflicting_sycl_function_attributes)
3757+ << DeclAttr << &A;
3758+ Diag (A.getLoc (), diag::note_conflicting_attribute);
3759+ return nullptr ;
3760+ }
3761+ }
3762+
36583763 // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr,
36593764 // check to see if the attribute holds equal values to
36603765 // (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
0 commit comments