@@ -3268,12 +3268,31 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
3268
3268
3269
3269
ASTContext &Ctx = S.getASTContext ();
3270
3270
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.
3271
3280
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) {
3275
3293
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);
3277
3296
Result &= false ;
3278
3297
}
3279
3298
}
@@ -3286,7 +3305,8 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
3286
3305
(getExprValue (AL.getArgAsExpr (2 ), Ctx) >=
3287
3306
getExprValue (A->getZDim (), Ctx)))) {
3288
3307
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);
3290
3310
Result &= false ;
3291
3311
}
3292
3312
}
@@ -3562,6 +3582,23 @@ static bool InvalidWorkGroupSizeAttrs(const Expr *MGValue, const Expr *XDim,
3562
3582
ZDimExpr->getResultAsAPSInt () != 1 ));
3563
3583
}
3564
3584
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
+
3565
3602
void Sema::AddSYCLIntelMaxWorkGroupSizeAttr (Decl *D,
3566
3603
const AttributeCommonInfo &CI,
3567
3604
Expr *XDim, Expr *YDim,
@@ -3595,6 +3632,40 @@ void Sema::AddSYCLIntelMaxWorkGroupSizeAttr(Decl *D,
3595
3632
if (!XDim || !YDim || !ZDim)
3596
3633
return ;
3597
3634
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
+
3598
3669
// If the declaration has a SYCLIntelMaxWorkGroupSizeAttr, check to see if
3599
3670
// the attribute holds equal values to (1, 1, 1) in case the value of
3600
3671
// SYCLIntelMaxGlobalWorkDimAttr equals to 0.
@@ -3655,6 +3726,40 @@ SYCLIntelMaxWorkGroupSizeAttr *Sema::MergeSYCLIntelMaxWorkGroupSizeAttr(
3655
3726
return nullptr ;
3656
3727
}
3657
3728
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
+
3658
3763
// If the declaration has a SYCLIntelMaxWorkGroupSizeAttr,
3659
3764
// check to see if the attribute holds equal values to
3660
3765
// (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
0 commit comments