@@ -3245,12 +3245,9 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
3245
3245
ASTContext &Ctx = S.getASTContext ();
3246
3246
3247
3247
if (const auto *A = D->getAttr <SYCLIntelMaxWorkGroupSizeAttr>()) {
3248
- if (!((getExprValue (AL.getArgAsExpr (0 ), Ctx) <=
3249
- getExprValue (A->getXDim (), Ctx)) &&
3250
- (getExprValue (AL.getArgAsExpr (1 ), Ctx) <=
3251
- getExprValue (A->getYDim (), Ctx)) &&
3252
- (getExprValue (AL.getArgAsExpr (2 ), Ctx) <=
3253
- getExprValue (A->getZDim (), Ctx)))) {
3248
+ if (!((getExprValue (AL.getArgAsExpr (0 ), Ctx) <= *A->getXDimVal ()) &&
3249
+ (getExprValue (AL.getArgAsExpr (1 ), Ctx) <= *A->getYDimVal ()) &&
3250
+ (getExprValue (AL.getArgAsExpr (2 ), Ctx) <= *A->getZDimVal ()))) {
3254
3251
S.Diag (AL.getLoc (), diag::err_conflicting_sycl_function_attributes)
3255
3252
<< AL << A->getSpelling ();
3256
3253
Result &= false ;
@@ -3272,19 +3269,18 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
3272
3269
return Result;
3273
3270
}
3274
3271
3275
- // Handles reqd_work_group_size and max_work_group_size .
3272
+ // Handles reqd_work_group_size.
3276
3273
template <typename WorkGroupAttr>
3277
3274
static void handleWorkGroupSize (Sema &S, Decl *D, const ParsedAttr &AL) {
3278
3275
if (D->isInvalidDecl ())
3279
3276
return ;
3280
3277
3281
3278
S.CheckDeprecatedSYCLAttributeSpelling (AL);
3282
- // __attribute__((reqd_work_group_size)), [[cl::reqd_work_group_size]], and
3283
- // [[intel::max_work_group_size]] all require exactly three arguments.
3279
+ // __attribute__((reqd_work_group_size)) and [[cl::reqd_work_group_size]]
3280
+ // all require exactly three arguments.
3284
3281
if ((AL.getKind () == ParsedAttr::AT_ReqdWorkGroupSize &&
3285
3282
AL.getAttributeSpellingListIndex () ==
3286
3283
ReqdWorkGroupSizeAttr::CXX11_cl_reqd_work_group_size) ||
3287
- AL.getKind () == ParsedAttr::AT_SYCLIntelMaxWorkGroupSize ||
3288
3284
AL.getSyntax () == ParsedAttr::AS_GNU) {
3289
3285
if (!AL.checkExactlyNumArgs (S, 3 ))
3290
3286
return ;
@@ -3348,8 +3344,8 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
3348
3344
}
3349
3345
}
3350
3346
3351
- // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or
3352
- // ReqdWorkGroupSizeAttr, check to see if they hold equal values
3347
+ // If the declaration has a ReqdWorkGroupSizeAttr,
3348
+ // check to see if they hold equal values
3353
3349
// (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
3354
3350
// equals to 0.
3355
3351
if (const auto *DeclAttr = D->getAttr <SYCLIntelMaxGlobalWorkDimAttr>()) {
@@ -3494,6 +3490,146 @@ static void handleWorkGroupSizeHint(Sema &S, Decl *D, const ParsedAttr &AL) {
3494
3490
AL.getArgAsExpr (2 ));
3495
3491
}
3496
3492
3493
+ // Handles max_work_group_size attribute.
3494
+ // If the [[intel::max_work_group_size(X, Y, Z)]] attribute is specified on a
3495
+ // declaration along with [[intel::max_global_work_dim()]] attribute,
3496
+ // check to see if all arguments of [[intel::max_work_group_size(X, Y, Z)]]
3497
+ // attribute hold value 1 in case the argument of
3498
+ // [[intel::max_global_work_dim()]] attribute equals to 0.
3499
+ static bool InvalidWorkGroupSizeAttrs (const Expr *MGValue, const Expr *XDim,
3500
+ const Expr *YDim, const Expr *ZDim) {
3501
+ // If any of the operand is still value dependent, we can't test anything.
3502
+ const auto *MGValueExpr = dyn_cast<ConstantExpr>(MGValue);
3503
+ const auto *XDimExpr = dyn_cast<ConstantExpr>(XDim);
3504
+ const auto *YDimExpr = dyn_cast<ConstantExpr>(YDim);
3505
+ const auto *ZDimExpr = dyn_cast<ConstantExpr>(ZDim);
3506
+
3507
+ if (!MGValueExpr || !XDimExpr || !YDimExpr || !ZDimExpr)
3508
+ return false ;
3509
+
3510
+ // Otherwise, check if the attribute values are equal to one.
3511
+ return (MGValueExpr->getResultAsAPSInt () == 0 &&
3512
+ (XDimExpr->getResultAsAPSInt () != 1 ||
3513
+ YDimExpr->getResultAsAPSInt () != 1 ||
3514
+ ZDimExpr->getResultAsAPSInt () != 1 ));
3515
+ }
3516
+
3517
+ void Sema::AddSYCLIntelMaxWorkGroupSizeAttr (Decl *D,
3518
+ const AttributeCommonInfo &CI,
3519
+ Expr *XDim, Expr *YDim,
3520
+ Expr *ZDim) {
3521
+ // Returns nullptr if diagnosing, otherwise returns the original expression
3522
+ // or the original expression converted to a constant expression.
3523
+ auto CheckAndConvertArg = [&](Expr *E) -> Expr * {
3524
+ // Check if the expression is not value dependent.
3525
+ if (!E->isValueDependent ()) {
3526
+ llvm::APSInt ArgVal;
3527
+ ExprResult Res = VerifyIntegerConstantExpression (E, &ArgVal);
3528
+ if (Res.isInvalid ())
3529
+ return nullptr ;
3530
+ E = Res.get ();
3531
+
3532
+ // This attribute requires a strictly positive value.
3533
+ if (ArgVal <= 0 ) {
3534
+ Diag (E->getExprLoc (), diag::err_attribute_requires_positive_integer)
3535
+ << CI << /* positive*/ 0 ;
3536
+ return nullptr ;
3537
+ }
3538
+ }
3539
+ return E;
3540
+ };
3541
+
3542
+ // Check all three argument values, and if any are bad, bail out. This will
3543
+ // convert the given expressions into constant expressions when possible.
3544
+ XDim = CheckAndConvertArg (XDim);
3545
+ YDim = CheckAndConvertArg (YDim);
3546
+ ZDim = CheckAndConvertArg (ZDim);
3547
+ if (!XDim || !YDim || !ZDim)
3548
+ return ;
3549
+
3550
+ // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr, check to see if
3551
+ // the attribute holds equal values to (1, 1, 1) in case the value of
3552
+ // SYCLIntelMaxGlobalWorkDimAttr equals to 0.
3553
+ if (const auto *DeclAttr = D->getAttr <SYCLIntelMaxGlobalWorkDimAttr>()) {
3554
+ if (InvalidWorkGroupSizeAttrs (DeclAttr->getValue (), XDim, YDim, ZDim)) {
3555
+ Diag (CI.getLoc (), diag::err_sycl_x_y_z_arguments_must_be_one)
3556
+ << CI << DeclAttr;
3557
+ return ;
3558
+ }
3559
+ }
3560
+
3561
+ // If the attribute was already applied with different arguments, then
3562
+ // diagnose the second attribute as a duplicate and don't add it.
3563
+ if (const auto *Existing = D->getAttr <SYCLIntelMaxWorkGroupSizeAttr>()) {
3564
+ DupArgResult Results[] = {AreArgValuesIdentical (XDim, Existing->getXDim ()),
3565
+ AreArgValuesIdentical (YDim, Existing->getYDim ()),
3566
+ AreArgValuesIdentical (ZDim, Existing->getZDim ())};
3567
+ // If any of the results are known to be different, we can diagnose at this
3568
+ // point and drop the attribute.
3569
+ if (llvm::is_contained (Results, DupArgResult::Different)) {
3570
+ Diag (CI.getLoc (), diag::warn_duplicate_attribute) << CI;
3571
+ Diag (Existing->getLoc (), diag::note_previous_attribute);
3572
+ return ;
3573
+ }
3574
+ // If all of the results are known to be the same, we can silently drop the
3575
+ // attribute. Otherwise, we have to add the attribute and resolve its
3576
+ // differences later.
3577
+ if (llvm::all_of (Results,
3578
+ [](DupArgResult V) { return V == DupArgResult::Same; }))
3579
+ return ;
3580
+ }
3581
+
3582
+ D->addAttr (::new (Context)
3583
+ SYCLIntelMaxWorkGroupSizeAttr (Context, CI, XDim, YDim, ZDim));
3584
+ }
3585
+
3586
+ SYCLIntelMaxWorkGroupSizeAttr *Sema::MergeSYCLIntelMaxWorkGroupSizeAttr (
3587
+ Decl *D, const SYCLIntelMaxWorkGroupSizeAttr &A) {
3588
+ // Check to see if there's a duplicate attribute already applied.
3589
+ if (const auto *DeclAttr = D->getAttr <SYCLIntelMaxWorkGroupSizeAttr>()) {
3590
+ DupArgResult Results[] = {
3591
+ AreArgValuesIdentical (DeclAttr->getXDim (), A.getXDim ()),
3592
+ AreArgValuesIdentical (DeclAttr->getYDim (), A.getYDim ()),
3593
+ AreArgValuesIdentical (DeclAttr->getZDim (), A.getZDim ())};
3594
+
3595
+ // If any of the results are known to be different, we can diagnose at this
3596
+ // point and drop the attribute.
3597
+ if (llvm::is_contained (Results, DupArgResult::Different)) {
3598
+ Diag (DeclAttr->getLoc (), diag::warn_duplicate_attribute) << &A;
3599
+ Diag (A.getLoc (), diag::note_previous_attribute);
3600
+ return nullptr ;
3601
+ }
3602
+ // If all of the results are known to be the same, we can silently drop the
3603
+ // attribute. Otherwise, we have to add the attribute and resolve its
3604
+ // differences later.
3605
+ if (llvm::all_of (Results,
3606
+ [](DupArgResult V) { return V == DupArgResult::Same; }))
3607
+ return nullptr ;
3608
+ }
3609
+
3610
+ // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr,
3611
+ // check to see if the attribute holds equal values to
3612
+ // (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
3613
+ // equals to 0.
3614
+ if (const auto *DeclAttr = D->getAttr <SYCLIntelMaxGlobalWorkDimAttr>()) {
3615
+ if (InvalidWorkGroupSizeAttrs (DeclAttr->getValue (), A.getXDim (),
3616
+ A.getYDim (), A.getZDim ())) {
3617
+ Diag (A.getLoc (), diag::err_sycl_x_y_z_arguments_must_be_one)
3618
+ << &A << DeclAttr;
3619
+ return nullptr ;
3620
+ }
3621
+ }
3622
+
3623
+ return ::new (Context) SYCLIntelMaxWorkGroupSizeAttr (
3624
+ Context, A, A.getXDim (), A.getYDim (), A.getZDim ());
3625
+ }
3626
+
3627
+ static void handleSYCLIntelMaxWorkGroupSize (Sema &S, Decl *D,
3628
+ const ParsedAttr &AL) {
3629
+ S.AddSYCLIntelMaxWorkGroupSizeAttr (D, AL, AL.getArgAsExpr (0 ),
3630
+ AL.getArgAsExpr (1 ), AL.getArgAsExpr (2 ));
3631
+ }
3632
+
3497
3633
void Sema::AddIntelReqdSubGroupSize (Decl *D, const AttributeCommonInfo &CI,
3498
3634
Expr *E) {
3499
3635
if (!E->isValueDependent ()) {
@@ -10371,7 +10507,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
10371
10507
handleWorkGroupSize<ReqdWorkGroupSizeAttr>(S, D, AL);
10372
10508
break ;
10373
10509
case ParsedAttr::AT_SYCLIntelMaxWorkGroupSize:
10374
- handleWorkGroupSize<SYCLIntelMaxWorkGroupSizeAttr> (S, D, AL);
10510
+ handleSYCLIntelMaxWorkGroupSize (S, D, AL);
10375
10511
break ;
10376
10512
case ParsedAttr::AT_IntelReqdSubGroupSize:
10377
10513
handleIntelReqdSubGroupSize (S, D, AL);
0 commit comments