@@ -3004,19 +3004,6 @@ static void handleWeakImportAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
3004
3004
// they hold equal values (1, 1, 1).
3005
3005
static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
3006
3006
bool Result = true;
3007
- auto checkZeroDim = [&S, &AL](auto &A, size_t X, size_t Y, size_t Z,
3008
- bool ReverseAttrs = false) -> bool {
3009
- if (X != 1 || Y != 1 || Z != 1) {
3010
- auto Diag =
3011
- S.Diag(AL.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one);
3012
- if (ReverseAttrs)
3013
- Diag << AL << A;
3014
- else
3015
- Diag << A << AL;
3016
- return false;
3017
- }
3018
- return true;
3019
- };
3020
3007
3021
3008
// Returns the unsigned constant integer value represented by
3022
3009
// given expression.
@@ -3026,30 +3013,6 @@ static bool checkWorkGroupSizeValues(Sema &S, Decl *D, const ParsedAttr &AL) {
3026
3013
3027
3014
ASTContext &Ctx = S.getASTContext();
3028
3015
3029
- if (AL.getKind() == ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim) {
3030
- ArrayRef<const Expr *> Dims;
3031
- Attr *B = nullptr;
3032
- if (const auto *B = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>())
3033
- Dims = B->dimensions();
3034
- else if (const auto *B = D->getAttr<ReqdWorkGroupSizeAttr>())
3035
- Dims = B->dimensions();
3036
- if (B) {
3037
- Result &=
3038
- checkZeroDim(B, getExprValue(Dims[0], Ctx),
3039
- getExprValue(Dims[1], Ctx), getExprValue(Dims[2], Ctx));
3040
- }
3041
- return Result;
3042
- }
3043
-
3044
- if (const auto *A = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
3045
- if ((A->getValue()->getIntegerConstantExpr(Ctx)->getSExtValue()) == 0) {
3046
- Result &= checkZeroDim(A, getExprValue(AL.getArgAsExpr(0), Ctx),
3047
- getExprValue(AL.getArgAsExpr(1), Ctx),
3048
- getExprValue(AL.getArgAsExpr(2), Ctx),
3049
- /*ReverseAttrs=*/true);
3050
- }
3051
- }
3052
-
3053
3016
if (const auto *A = D->getAttr<SYCLIntelMaxWorkGroupSizeAttr>()) {
3054
3017
if (!((getExprValue(AL.getArgAsExpr(0), Ctx) <=
3055
3018
getExprValue(A->getXDim(), Ctx)) &&
@@ -3159,6 +3122,27 @@ static void handleWorkGroupSize(Sema &S, Decl *D, const ParsedAttr &AL) {
3159
3122
}
3160
3123
}
3161
3124
3125
+ // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or
3126
+ // ReqdWorkGroupSizeAttr, check to see if they hold equal values
3127
+ // (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
3128
+ // equals to 0.
3129
+ if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
3130
+ if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
3131
+ // If the value is dependent, we can not test anything.
3132
+ if (!DeclExpr)
3133
+ return;
3134
+
3135
+ // Test the attribute value.
3136
+ if (DeclExpr->getResultAsAPSInt() == 0 &&
3137
+ (XDimVal.getZExtValue() != 1 || YDimVal.getZExtValue() != 1 ||
3138
+ ZDimVal.getZExtValue() != 1)) {
3139
+ S.Diag(AL.getLoc(), diag::err_sycl_x_y_z_arguments_must_be_one)
3140
+ << AL << DeclAttr;
3141
+ return;
3142
+ }
3143
+ }
3144
+ }
3145
+
3162
3146
if (const auto *ExistingAttr = D->getAttr<WorkGroupAttr>()) {
3163
3147
// Compare attribute arguments value and warn for a mismatch.
3164
3148
if (ExistingAttr->getXDimVal(Ctx) != XDimVal ||
@@ -3661,23 +3645,130 @@ static void handleSYCLIntelSchedulerTargetFmaxMhzAttr(Sema &S, Decl *D,
3661
3645
}
3662
3646
3663
3647
// Handles max_global_work_dim.
3664
- static void handleMaxGlobalWorkDimAttr(Sema &S, Decl *D, const ParsedAttr &A) {
3665
- if (D->isInvalidDecl())
3666
- return;
3648
+ // Returns a OneArgResult value; EqualToOne means all argument values are
3649
+ // equal to one, NotEqualToOne means at least one argument value is not
3650
+ // equal to one, and Unknown means that at least one of the argument values
3651
+ // could not be determined.
3652
+ enum class OneArgResult { Unknown, EqualToOne, NotEqualToOne };
3653
+ static OneArgResult AreAllArgsOne(const Expr *Args[], size_t Count) {
3654
+
3655
+ for (size_t Idx = 0; Idx < Count; ++Idx) {
3656
+ const auto *CE = dyn_cast<ConstantExpr>(Args[Idx]);
3657
+ if (!CE)
3658
+ return OneArgResult::Unknown;
3659
+ if (CE->getResultAsAPSInt() != 1)
3660
+ return OneArgResult::NotEqualToOne;
3661
+ }
3662
+ return OneArgResult::EqualToOne;
3663
+ }
3664
+
3665
+ // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or
3666
+ // ReqdWorkGroupSizeAttr, check to see if they hold equal values
3667
+ // (1, 1, 1). Returns true if diagnosed.
3668
+ template <typename AttrTy>
3669
+ static bool checkWorkGroupSizeAttrExpr(Sema &S, Decl *D,
3670
+ const AttributeCommonInfo &AL) {
3671
+ if (const auto *A = D->getAttr<AttrTy>()) {
3672
+ const Expr *Args[3] = {A->getXDim(), A->getYDim(), A->getZDim()};
3673
+ if (OneArgResult::NotEqualToOne == AreAllArgsOne(Args, 3)) {
3674
+ S.Diag(A->getLocation(), diag::err_sycl_x_y_z_arguments_must_be_one)
3675
+ << A << AL;
3676
+ return true;
3677
+ }
3678
+ }
3679
+ return false;
3680
+ }
3667
3681
3668
- Expr *E = A.getArgAsExpr(0);
3682
+ void Sema::AddSYCLIntelMaxGlobalWorkDimAttr(Decl *D,
3683
+ const AttributeCommonInfo &CI,
3684
+ Expr *E) {
3685
+ if (!E->isValueDependent()) {
3686
+ // Validate that we have an integer constant expression and then store the
3687
+ // converted constant expression into the semantic attribute so that we
3688
+ // don't have to evaluate it again later.
3689
+ llvm::APSInt ArgVal;
3690
+ ExprResult Res = VerifyIntegerConstantExpression(E, &ArgVal);
3691
+ if (Res.isInvalid())
3692
+ return;
3693
+ E = Res.get();
3669
3694
3670
- if (!checkWorkGroupSizeValues(S, D, A)) {
3671
- D->setInvalidDecl();
3672
- return;
3695
+ // This attribute must be in the range [0, 3].
3696
+ if (ArgVal < 0 || ArgVal > 3) {
3697
+ Diag(E->getBeginLoc(), diag::err_attribute_argument_out_of_range)
3698
+ << CI << 0 << 3 << E->getSourceRange();
3699
+ return;
3700
+ }
3701
+
3702
+ // Check to see if there's a duplicate attribute with different values
3703
+ // already applied to the declaration.
3704
+ if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
3705
+ // If the other attribute argument is instantiation dependent, we won't
3706
+ // have converted it to a constant expression yet and thus we test
3707
+ // whether this is a null pointer.
3708
+ if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
3709
+ if (ArgVal != DeclExpr->getResultAsAPSInt()) {
3710
+ Diag(CI.getLoc(), diag::warn_duplicate_attribute) << CI;
3711
+ Diag(DeclAttr->getLoc(), diag::note_previous_attribute);
3712
+ }
3713
+ // Drop the duplicate attribute.
3714
+ return;
3715
+ }
3716
+ }
3717
+
3718
+ // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or
3719
+ // ReqdWorkGroupSizeAttr, check to see if they hold equal values
3720
+ // (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
3721
+ // equals to 0.
3722
+ if (ArgVal == 0) {
3723
+ if (checkWorkGroupSizeAttrExpr<SYCLIntelMaxWorkGroupSizeAttr>(*this, D,
3724
+ CI) ||
3725
+ checkWorkGroupSizeAttrExpr<ReqdWorkGroupSizeAttr>(*this, D, CI))
3726
+ return;
3727
+ }
3673
3728
}
3674
3729
3675
- if ( D->getAttr< SYCLIntelMaxGlobalWorkDimAttr>())
3676
- S.Diag(A.getLoc(), diag::warn_duplicate_attribute) << A;
3730
+ D->addAttr(::new (Context) SYCLIntelMaxGlobalWorkDimAttr(Context, CI, E));
3731
+ }
3677
3732
3678
- S.CheckDeprecatedSYCLAttributeSpelling(A);
3733
+ SYCLIntelMaxGlobalWorkDimAttr *Sema::MergeSYCLIntelMaxGlobalWorkDimAttr(
3734
+ Decl *D, const SYCLIntelMaxGlobalWorkDimAttr &A) {
3735
+ // Check to see if there's a duplicate attribute with different values
3736
+ // already applied to the declaration.
3737
+ if (const auto *DeclAttr = D->getAttr<SYCLIntelMaxGlobalWorkDimAttr>()) {
3738
+ if (const auto *DeclExpr = dyn_cast<ConstantExpr>(DeclAttr->getValue())) {
3739
+ if (const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue())) {
3740
+ if (DeclExpr->getResultAsAPSInt() != MergeExpr->getResultAsAPSInt()) {
3741
+ Diag(DeclAttr->getLoc(), diag::warn_duplicate_attribute) << &A;
3742
+ Diag(A.getLoc(), diag::note_previous_attribute);
3743
+ }
3744
+ // Do not add a duplicate attribute.
3745
+ return nullptr;
3746
+ }
3747
+ }
3748
+ }
3749
+
3750
+ // If the declaration has a SYCLIntelMaxWorkGroupSizeAttr or
3751
+ // ReqdWorkGroupSizeAttr, check to see if they hold equal values
3752
+ // (1, 1, 1) in case the value of SYCLIntelMaxGlobalWorkDimAttr
3753
+ // equals to 0.
3754
+ const auto *MergeExpr = dyn_cast<ConstantExpr>(A.getValue());
3755
+ if (MergeExpr->getResultAsAPSInt() == 0) {
3756
+ if (checkWorkGroupSizeAttrExpr<SYCLIntelMaxWorkGroupSizeAttr>(*this, D,
3757
+ A) ||
3758
+ checkWorkGroupSizeAttrExpr<ReqdWorkGroupSizeAttr>(*this, D, A))
3759
+ return nullptr;
3760
+ }
3679
3761
3680
- S.addIntelSingleArgAttr<SYCLIntelMaxGlobalWorkDimAttr>(D, A, E);
3762
+ return ::new (Context)
3763
+ SYCLIntelMaxGlobalWorkDimAttr(Context, A, A.getValue());
3764
+ }
3765
+
3766
+ static void handleSYCLIntelMaxGlobalWorkDimAttr(Sema &S, Decl *D,
3767
+ const ParsedAttr &AL) {
3768
+ S.CheckDeprecatedSYCLAttributeSpelling(AL);
3769
+
3770
+ Expr *E = AL.getArgAsExpr(0);
3771
+ S.AddSYCLIntelMaxGlobalWorkDimAttr(D, AL, E);
3681
3772
}
3682
3773
3683
3774
// Handles [[intel::loop_fuse]] and [[intel::loop_fuse_independent]].
@@ -5250,14 +5341,6 @@ static void handleSYCLDeviceAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5250
5341
}
5251
5342
5252
5343
handleSimpleAttribute<SYCLDeviceAttr>(S, D, AL);
5253
- // constexpr variable may already get an implicit constant attr, which should
5254
- // be replaced by the explicit constant attr.
5255
- if (auto *A = D->getAttr<CUDAConstantAttr>()) {
5256
- if (!A->isImplicit())
5257
- return;
5258
- D->dropAttr<CUDAConstantAttr>();
5259
- }
5260
- D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL));
5261
5344
}
5262
5345
5263
5346
static void handleSYCLDeviceIndirectlyCallableAttr(Sema &S, Decl *D,
@@ -5355,6 +5438,13 @@ static void handleConstantAttr(Sema &S, Decl *D, const ParsedAttr &AL) {
5355
5438
S.Diag(AL.getLoc(), diag::err_cuda_nonstatic_constdev);
5356
5439
return;
5357
5440
}
5441
+ // constexpr variable may already get an implicit constant attr, which should
5442
+ // be replaced by the explicit constant attr.
5443
+ if (auto *A = D->getAttr<CUDAConstantAttr>()) {
5444
+ if (!A->isImplicit())
5445
+ return;
5446
+ D->dropAttr<CUDAConstantAttr>();
5447
+ }
5358
5448
D->addAttr(::new (S.Context) CUDAConstantAttr(S.Context, AL));
5359
5449
}
5360
5450
@@ -9554,7 +9644,7 @@ static void ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D,
9554
9644
handleSYCLIntelSchedulerTargetFmaxMhzAttr(S, D, AL);
9555
9645
break;
9556
9646
case ParsedAttr::AT_SYCLIntelMaxGlobalWorkDim:
9557
- handleMaxGlobalWorkDimAttr (S, D, AL);
9647
+ handleSYCLIntelMaxGlobalWorkDimAttr (S, D, AL);
9558
9648
break;
9559
9649
case ParsedAttr::AT_SYCLIntelNoGlobalWorkOffset:
9560
9650
handleSYCLIntelNoGlobalWorkOffsetAttr(S, D, AL);
0 commit comments