@@ -62,14 +62,15 @@ class DSAStackTy {
62
62
struct DSAVarData {
63
63
OpenMPDirectiveKind DKind = OMPD_unknown;
64
64
OpenMPClauseKind CKind = OMPC_unknown;
65
+ unsigned Modifier = 0;
65
66
const Expr *RefExpr = nullptr;
66
67
DeclRefExpr *PrivateCopy = nullptr;
67
68
SourceLocation ImplicitDSALoc;
68
69
DSAVarData() = default;
69
70
DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
70
71
const Expr *RefExpr, DeclRefExpr *PrivateCopy,
71
- SourceLocation ImplicitDSALoc)
72
- : DKind(DKind), CKind(CKind), RefExpr(RefExpr),
72
+ SourceLocation ImplicitDSALoc, unsigned Modifier )
73
+ : DKind(DKind), CKind(CKind), Modifier(Modifier), RefExpr(RefExpr),
73
74
PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
74
75
};
75
76
using OperatorOffsetTy =
@@ -80,6 +81,7 @@ class DSAStackTy {
80
81
private:
81
82
struct DSAInfo {
82
83
OpenMPClauseKind Attributes = OMPC_unknown;
84
+ unsigned Modifier = 0;
83
85
/// Pointer to a reference expression and a flag which shows that the
84
86
/// variable is marked as lastprivate(true) or not (false).
85
87
llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
@@ -164,6 +166,8 @@ class DSAStackTy {
164
166
/// List of globals marked as declare target link in this target region
165
167
/// (isOpenMPTargetExecutionDirective(Directive) == true).
166
168
llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
169
+ /// List of decls used in inclusive/exclusive clauses of the scan directive.
170
+ llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
167
171
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
168
172
Scope *CurScope, SourceLocation Loc)
169
173
: Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -469,9 +473,21 @@ class DSAStackTy {
469
473
/// parent directive.
470
474
const ValueDecl *getParentLoopControlVariable(unsigned I) const;
471
475
476
+ /// Marks the specified decl \p D as used in scan directive.
477
+ void markDeclAsUsedInScanDirective(ValueDecl *D) {
478
+ SharingMapTy *Stack = getSecondOnStackOrNull();
479
+ Stack->UsedInScanDirective.insert(D);
480
+ }
481
+
482
+ /// Checks if the specified declaration was used in the inner scan directive.
483
+ bool isUsedInScanDirective(ValueDecl *D) const {
484
+ const SharingMapTy &Stack = getTopOfStack();
485
+ return Stack.UsedInScanDirective.count(D) > 0;
486
+ }
487
+
472
488
/// Adds explicit data sharing attribute to the specified declaration.
473
489
void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
474
- DeclRefExpr *PrivateCopy = nullptr);
490
+ DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0 );
475
491
476
492
/// Adds additional information for the reduction items with the reduction id
477
493
/// represented as an operator.
@@ -1079,6 +1095,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
1079
1095
DVar.PrivateCopy = Data.PrivateCopy;
1080
1096
DVar.CKind = Data.Attributes;
1081
1097
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1098
+ DVar.Modifier = Data.Modifier;
1082
1099
return DVar;
1083
1100
}
1084
1101
@@ -1226,19 +1243,21 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
1226
1243
}
1227
1244
1228
1245
void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1229
- DeclRefExpr *PrivateCopy) {
1246
+ DeclRefExpr *PrivateCopy, unsigned Modifier ) {
1230
1247
D = getCanonicalDecl(D);
1231
1248
if (A == OMPC_threadprivate) {
1232
1249
DSAInfo &Data = Threadprivates[D];
1233
1250
Data.Attributes = A;
1234
1251
Data.RefExpr.setPointer(E);
1235
1252
Data.PrivateCopy = nullptr;
1253
+ Data.Modifier = Modifier;
1236
1254
} else {
1237
1255
DSAInfo &Data = getTopOfStack().SharingMap[D];
1238
1256
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
1239
1257
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
1240
1258
(A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
1241
1259
(isLoopControlVariable(D).first && A == OMPC_private));
1260
+ Data.Modifier = Modifier;
1242
1261
if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
1243
1262
Data.RefExpr.setInt(/*IntVal=*/true);
1244
1263
return;
@@ -1250,6 +1269,7 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1250
1269
Data.PrivateCopy = PrivateCopy;
1251
1270
if (PrivateCopy) {
1252
1271
DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1272
+ Data.Modifier = Modifier;
1253
1273
Data.Attributes = A;
1254
1274
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
1255
1275
Data.PrivateCopy = nullptr;
@@ -1355,7 +1375,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1355
1375
"set.");
1356
1376
TaskgroupDescriptor = I->TaskgroupReductionRef;
1357
1377
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
1358
- Data.PrivateCopy, I->DefaultAttrLoc);
1378
+ Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0 );
1359
1379
}
1360
1380
return DSAVarData();
1361
1381
}
@@ -1380,7 +1400,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
1380
1400
"set.");
1381
1401
TaskgroupDescriptor = I->TaskgroupReductionRef;
1382
1402
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
1383
- Data.PrivateCopy, I->DefaultAttrLoc);
1403
+ Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0 );
1384
1404
}
1385
1405
return DSAVarData();
1386
1406
}
@@ -1455,6 +1475,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1455
1475
if (TI != Threadprivates.end()) {
1456
1476
DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
1457
1477
DVar.CKind = OMPC_threadprivate;
1478
+ DVar.Modifier = TI->getSecond().Modifier;
1458
1479
return DVar;
1459
1480
}
1460
1481
if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
@@ -1546,6 +1567,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1546
1567
DVar.CKind = Data.Attributes;
1547
1568
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1548
1569
DVar.DKind = I->Directive;
1570
+ DVar.Modifier = Data.Modifier;
1549
1571
return DVar;
1550
1572
}
1551
1573
@@ -1592,6 +1614,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
1592
1614
DVar.CKind = Data.Attributes;
1593
1615
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
1594
1616
DVar.DKind = I->Directive;
1617
+ DVar.Modifier = Data.Modifier;
1595
1618
}
1596
1619
1597
1620
return DVar;
@@ -2299,11 +2322,64 @@ void Sema::EndOpenMPClause() {
2299
2322
DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
2300
2323
}
2301
2324
2302
- static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2303
- ArrayRef<OMPClause *> Clauses);
2304
2325
static std::pair<ValueDecl *, bool>
2305
2326
getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
2306
2327
SourceRange &ERange, bool AllowArraySection = false);
2328
+
2329
+ /// Check consistency of the reduction clauses.
2330
+ static void checkReductionClauses(Sema &S, DSAStackTy *Stack,
2331
+ ArrayRef<OMPClause *> Clauses) {
2332
+ bool InscanFound = false;
2333
+ SourceLocation InscanLoc;
2334
+ // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions.
2335
+ // A reduction clause without the inscan reduction-modifier may not appear on
2336
+ // a construct on which a reduction clause with the inscan reduction-modifier
2337
+ // appears.
2338
+ for (OMPClause *C : Clauses) {
2339
+ if (C->getClauseKind() != OMPC_reduction)
2340
+ continue;
2341
+ auto *RC = cast<OMPReductionClause>(C);
2342
+ if (RC->getModifier() == OMPC_REDUCTION_inscan) {
2343
+ InscanFound = true;
2344
+ InscanLoc = RC->getModifierLoc();
2345
+ break;
2346
+ }
2347
+ }
2348
+ if (InscanFound) {
2349
+ for (OMPClause *C : Clauses) {
2350
+ if (C->getClauseKind() != OMPC_reduction)
2351
+ continue;
2352
+ auto *RC = cast<OMPReductionClause>(C);
2353
+ if (RC->getModifier() != OMPC_REDUCTION_inscan) {
2354
+ S.Diag(RC->getModifier() == OMPC_REDUCTION_unknown
2355
+ ? RC->getBeginLoc()
2356
+ : RC->getModifierLoc(),
2357
+ diag::err_omp_inscan_reduction_expected);
2358
+ S.Diag(InscanLoc, diag::note_omp_previous_inscan_reduction);
2359
+ continue;
2360
+ }
2361
+ for (Expr *Ref : RC->varlists()) {
2362
+ assert(Ref && "NULL expr in OpenMP nontemporal clause.");
2363
+ SourceLocation ELoc;
2364
+ SourceRange ERange;
2365
+ Expr *SimpleRefExpr = Ref;
2366
+ auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
2367
+ /*AllowArraySection=*/true);
2368
+ ValueDecl *D = Res.first;
2369
+ if (!D)
2370
+ continue;
2371
+ if (!Stack->isUsedInScanDirective(getCanonicalDecl(D))) {
2372
+ S.Diag(Ref->getExprLoc(),
2373
+ diag::err_omp_reduction_not_inclusive_exclusive)
2374
+ << Ref->getSourceRange();
2375
+ }
2376
+ }
2377
+ }
2378
+ }
2379
+ }
2380
+
2381
+ static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2382
+ ArrayRef<OMPClause *> Clauses);
2307
2383
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
2308
2384
bool WithInit);
2309
2385
@@ -2380,6 +2456,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
2380
2456
// Check allocate clauses.
2381
2457
if (!CurContext->isDependentContext())
2382
2458
checkAllocateClauses(*this, DSAStack, D->clauses());
2459
+ checkReductionClauses(*this, DSAStack, D->clauses());
2383
2460
}
2384
2461
2385
2462
DSAStack->pop();
@@ -4177,7 +4254,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4177
4254
if (ParentRegion == OMPD_unknown &&
4178
4255
!isOpenMPNestingTeamsDirective(CurrentRegion) &&
4179
4256
CurrentRegion != OMPD_cancellation_point &&
4180
- CurrentRegion != OMPD_cancel)
4257
+ CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan )
4181
4258
return false;
4182
4259
if (CurrentRegion == OMPD_cancellation_point ||
4183
4260
CurrentRegion == OMPD_cancel) {
@@ -4298,7 +4375,8 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
4298
4375
NestingProhibited =
4299
4376
SemaRef.LangOpts.OpenMP < 50 ||
4300
4377
(ParentRegion != OMPD_simd && ParentRegion != OMPD_for &&
4301
- ParentRegion != OMPD_for_simd);
4378
+ ParentRegion != OMPD_for_simd && ParentRegion != OMPD_parallel_for &&
4379
+ ParentRegion != OMPD_parallel_for_simd);
4302
4380
OrphanSeen = ParentRegion == OMPD_unknown;
4303
4381
Recommend = ShouldBeInLoopSimdRegion;
4304
4382
}
@@ -13971,9 +14049,11 @@ struct ReductionData {
13971
14049
SmallVector<Decl *, 4> ExprCaptures;
13972
14050
/// List of postupdate expressions.
13973
14051
SmallVector<Expr *, 4> ExprPostUpdates;
14052
+ /// Reduction modifier.
14053
+ unsigned RedModifier = 0;
13974
14054
ReductionData() = delete;
13975
14055
/// Reserves required memory for the reduction data.
13976
- ReductionData(unsigned Size) {
14056
+ ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier ) {
13977
14057
Vars.reserve(Size);
13978
14058
Privates.reserve(Size);
13979
14059
LHSs.reserve(Size);
@@ -14691,7 +14771,8 @@ static bool actOnOMPReductionKindClause(
14691
14771
}
14692
14772
// All reduction items are still marked as reduction (to do not increase
14693
14773
// code base size).
14694
- Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
14774
+ Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref,
14775
+ RD.RedModifier);
14695
14776
if (CurrDir == OMPD_taskgroup) {
14696
14777
if (DeclareReductionRef.isUsable())
14697
14778
Stack->addTaskgroupReductionData(D, ReductionIdRange,
@@ -14718,8 +14799,22 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
14718
14799
<< getOpenMPClauseName(OMPC_reduction);
14719
14800
return nullptr;
14720
14801
}
14802
+ // OpenMP 5.0, 2.19.5.4 reduction Clause, Restrictions
14803
+ // A reduction clause with the inscan reduction-modifier may only appear on a
14804
+ // worksharing-loop construct, a worksharing-loop SIMD construct, a simd
14805
+ // construct, a parallel worksharing-loop construct or a parallel
14806
+ // worksharing-loop SIMD construct.
14807
+ if (Modifier == OMPC_REDUCTION_inscan &&
14808
+ (DSAStack->getCurrentDirective() != OMPD_for &&
14809
+ DSAStack->getCurrentDirective() != OMPD_for_simd &&
14810
+ DSAStack->getCurrentDirective() != OMPD_simd &&
14811
+ DSAStack->getCurrentDirective() != OMPD_parallel_for &&
14812
+ DSAStack->getCurrentDirective() != OMPD_parallel_for_simd)) {
14813
+ Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
14814
+ return nullptr;
14815
+ }
14721
14816
14722
- ReductionData RD(VarList.size());
14817
+ ReductionData RD(VarList.size(), Modifier );
14723
14818
if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
14724
14819
StartLoc, LParenLoc, ColonLoc, EndLoc,
14725
14820
ReductionIdScopeSpec, ReductionId,
@@ -18021,6 +18116,19 @@ OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
18021
18116
if (!D)
18022
18117
continue;
18023
18118
18119
+ const DSAStackTy::DSAVarData DVar =
18120
+ DSAStack->getTopDSA(D, /*FromParent=*/true);
18121
+ // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
18122
+ // A list item that appears in the inclusive or exclusive clause must appear
18123
+ // in a reduction clause with the inscan modifier on the enclosing
18124
+ // worksharing-loop, worksharing-loop SIMD, or simd construct.
18125
+ if (DVar.CKind != OMPC_reduction ||
18126
+ DVar.Modifier != OMPC_REDUCTION_inscan)
18127
+ Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
18128
+ << RefExpr->getSourceRange();
18129
+
18130
+ if (DSAStack->getParentDirective() != OMPD_unknown)
18131
+ DSAStack->markDeclAsUsedInScanDirective(D);
18024
18132
Vars.push_back(RefExpr);
18025
18133
}
18026
18134
@@ -18049,6 +18157,19 @@ OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
18049
18157
if (!D)
18050
18158
continue;
18051
18159
18160
+ const DSAStackTy::DSAVarData DVar =
18161
+ DSAStack->getTopDSA(D, /*FromParent=*/true);
18162
+ // OpenMP 5.0, 2.9.6, scan Directive, Restrictions.
18163
+ // A list item that appears in the inclusive or exclusive clause must appear
18164
+ // in a reduction clause with the inscan modifier on the enclosing
18165
+ // worksharing-loop, worksharing-loop SIMD, or simd construct.
18166
+ if (DVar.CKind != OMPC_reduction ||
18167
+ DVar.Modifier != OMPC_REDUCTION_inscan)
18168
+ Diag(ELoc, diag::err_omp_inclusive_exclusive_not_reduction)
18169
+ << RefExpr->getSourceRange();
18170
+
18171
+ if (DSAStack->getParentDirective() != OMPD_unknown)
18172
+ DSAStack->markDeclAsUsedInScanDirective(D);
18052
18173
Vars.push_back(RefExpr);
18053
18174
}
18054
18175
0 commit comments