@@ -3430,23 +3430,103 @@ static void handleSYCLIntelSchedulerTargetFmaxMhzAttr(Sema &S, Decl *D,
3430
3430
}
3431
3431
3432
3432
// Handles max_global_work_dim.
3433
- static void handleMaxGlobalWorkDimAttr (Sema &S, Decl *D, const ParsedAttr &A) {
3434
- if (D->isInvalidDecl ())
3435
- return ;
3436
-
3437
- Expr *E = A.getArgAsExpr (0 );
3433
+ void Sema::AddSYCLIntelMaxGlobalWorkDimAttr (Decl *D,
3434
+ const AttributeCommonInfo &CI,
3435
+ Expr *E) {
3436
+ if (!E->isValueDependent ()) {
3437
+ // Validate that we have an integer constant expression and then store the
3438
+ // converted constant expression into the semantic attribute so that we
3439
+ // don't have to evaluate it again later.
3440
+ llvm::APSInt ArgVal;
3441
+ ExprResult Res = VerifyIntegerConstantExpression (E, &ArgVal);
3442
+ if (Res.isInvalid ())
3443
+ return ;
3444
+ E = Res.get ();
3438
3445
3439
- if (!checkWorkGroupSizeValues (S, D, A)) {
3440
- D->setInvalidDecl ();
3441
- return ;
3446
+ // This attribute requires a non-negative value.
3447
+ if (ArgVal < 0 ) {
3448
+ Diag (E->getExprLoc (), diag::err_attribute_requires_positive_integer)
3449
+ << CI << /* non-negative*/ 1 ;
3450
+ return ;
3451
+ }
3452
+ // This attribute must be in the range [0, 3].
3453
+ if (ArgVal > 3 ) {
3454
+ Diag (E->getBeginLoc (), diag::err_attribute_argument_out_of_range)
3455
+ << CI << 0 << 3 << E->getSourceRange ();
3456
+ return ;
3457
+ }
3458
+ // Check to see if there's a duplicate attribute with different values
3459
+ // already applied to the declaration.
3460
+ if (const auto *DeclAttr =
3461
+ D->getAttr <SYCLIntelMaxGlobalWorkDimAttr>()) {
3462
+ // If the other attribute argument is instantiation dependent, we won't
3463
+ // have converted it to a constant expression yet and thus we test
3464
+ // whether this is a null pointer.
3465
+ const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue ());
3466
+ if (DeclExpr && ArgVal != DeclExpr->getResultAsAPSInt ()) {
3467
+ Diag (CI.getLoc (), diag::warn_duplicate_attribute) << CI;
3468
+ Diag (DeclAttr->getLoc (), diag::note_previous_attribute);
3469
+ return ;
3470
+ }
3471
+ }
3472
+ // If the declaration has an [[intel::reqd_work_group_size()]] or
3473
+ // [[cl::reqd_work_group_size()]] attribute, check to see if they
3474
+ // hold equal values (1, 1, 1) in case the value of
3475
+ // [[intel::max_global_work_dim()]] attribute equals to 0.
3476
+ if (const auto *DeclAttr = D->getAttr <ReqdWorkGroupSizeAttr>()) {
3477
+ Optional<llvm::APSInt> XDimVal = DeclAttr->getXDimVal (Context);
3478
+ Optional<llvm::APSInt> YDimVal = DeclAttr->getYDimVal (Context);
3479
+ Optional<llvm::APSInt> ZDimVal = DeclAttr->getZDimVal (Context);
3480
+ if ((ArgVal == 0 ) && (*XDimVal != 1 || *YDimVal != 1 || *ZDimVal != 1 )) {
3481
+ Diag (DeclAttr->getLocation (), diag::err_sycl_x_y_z_arguments_must_be_one)
3482
+ << DeclAttr << CI;
3483
+ return ;
3484
+ }
3485
+ }
3486
+ // If the declaration has an [[intel::max_work_group_size()]]
3487
+ // attribute, check to see if it holds equal values (1, 1, 1) in
3488
+ // case the value of [[intel::max_global_work_dim()]] attribute equals to 0.
3489
+ if (const auto *DeclAttr = D->getAttr <SYCLIntelMaxWorkGroupSizeAttr>()) {
3490
+ Optional<llvm::APSInt> XDimVal = DeclAttr->getXDimVal (Context);
3491
+ Optional<llvm::APSInt> YDimVal = DeclAttr->getYDimVal (Context);
3492
+ Optional<llvm::APSInt> ZDimVal = DeclAttr->getZDimVal (Context);
3493
+ if ((ArgVal == 0 ) && (*XDimVal != 1 || *YDimVal != 1 || *ZDimVal != 1 )) {
3494
+ Diag (DeclAttr->getLocation (), diag::err_sycl_x_y_z_arguments_must_be_one)
3495
+ << DeclAttr << CI;
3496
+ return ;
3497
+ }
3498
+ }
3442
3499
}
3443
3500
3444
- if (D->getAttr <SYCLIntelMaxGlobalWorkDimAttr>())
3445
- S.Diag (A.getLoc (), diag::warn_duplicate_attribute) << A;
3501
+ D->addAttr (::new (Context)
3502
+ SYCLIntelMaxGlobalWorkDimAttr (Context, CI, E));
3503
+ }
3446
3504
3447
- S.CheckDeprecatedSYCLAttributeSpelling (A);
3505
+ SYCLIntelMaxGlobalWorkDimAttr *Sema::MergeSYCLIntelMaxGlobalWorkDimAttr (
3506
+ Decl *D, const SYCLIntelMaxGlobalWorkDimAttr &A) {
3507
+ // Check to see if there's a duplicate attribute with different values
3508
+ // already applied to the declaration.
3509
+ if (const auto *DeclAttr =
3510
+ D->getAttr <SYCLIntelMaxGlobalWorkDimAttr>()) {
3511
+ const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue ());
3512
+ const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue ());
3513
+ if (DeclExpr && MergeExpr &&
3514
+ DeclExpr->getResultAsAPSInt () != MergeExpr->getResultAsAPSInt ()) {
3515
+ Diag (DeclAttr->getLoc (), diag::warn_duplicate_attribute) << &A;
3516
+ Diag (A.getLoc (), diag::note_previous_attribute);
3517
+ return nullptr ;
3518
+ }
3519
+ }
3520
+ return ::new (Context)
3521
+ SYCLIntelMaxGlobalWorkDimAttr (Context, A, A.getValue ());
3522
+ }
3448
3523
3449
- S.addIntelSingleArgAttr <SYCLIntelMaxGlobalWorkDimAttr>(D, A, E);
3524
+ static void handleSYCLIntelMaxGlobalWorkDimAttr (Sema &S, Decl *D,
3525
+ const ParsedAttr &AL) {
3526
+ S.CheckDeprecatedSYCLAttributeSpelling (AL);
3527
+
3528
+ Expr *E = AL.getArgAsExpr (0 );
3529
+ S.AddSYCLIntelMaxGlobalWorkDimAttr (D, AL, E);
3450
3530
}
3451
3531
3452
3532
// Handles [[intel::loop_fuse]] and [[intel::loop_fuse_independent]].
@@ -9129,7 +9209,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
9129
9209
handleSYCLIntelSchedulerTargetFmaxMhzAttr (S, D, AL);
9130
9210
break ;
9131
9211
case ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim:
9132
- handleMaxGlobalWorkDimAttr (S, D, AL);
9212
+ handleSYCLIntelMaxGlobalWorkDimAttr (S, D, AL);
9133
9213
break ;
9134
9214
case ParsedAttr::AT_SYCLIntelNoGlobalWorkOffset:
9135
9215
handleSYCLIntelNoGlobalWorkOffsetAttr (S, D, AL);
0 commit comments