Skip to content

Commit 8099e0f

Browse files
committed
[OPENMP50]Add basic support for inscan reduction modifier.
Added basic support (parsing/sema checks) for the inscan modifier in the reduction clauses.
1 parent 6a9ad5f commit 8099e0f

File tree

8 files changed

+264
-98
lines changed

8 files changed

+264
-98
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9863,7 +9863,7 @@ def err_omp_prohibited_region : Error<
98639863
"; perhaps you forget to enclose 'omp %3' directive into a for or a parallel for region with 'ordered' clause?|"
98649864
"; perhaps you forget to enclose 'omp %3' directive into a target region?|"
98659865
"; perhaps you forget to enclose 'omp %3' directive into a teams region?|"
9866-
"; perhaps you forget to enclose 'omp %3' directive into a for, simd, or for simd region?}2">;
9866+
"; perhaps you forget to enclose 'omp %3' directive into a for, simd, for simd, parallel for, or parallel for simd region?}2">;
98679867
def err_omp_prohibited_region_simd : Error<
98689868
"OpenMP constructs may not be nested inside a simd region%select{| except for ordered simd, simd, scan, or atomic directive}0">;
98699869
def err_omp_prohibited_region_atomic : Error<
@@ -10060,7 +10060,8 @@ def warn_omp_nesting_simd : Warning<
1006010060
InGroup<SourceUsesOpenMP>;
1006110061
def err_omp_orphaned_device_directive : Error<
1006210062
"orphaned 'omp %0' directives are prohibited"
10063-
"; perhaps you forget to enclose the directive into a %select{|||target |teams|for, simd, or for simd }1region?">;
10063+
"; perhaps you forget to enclose the directive into a "
10064+
"%select{|||target |teams|for, simd, for simd, parallel for, or parallel for simd }1region?">;
1006410065
def err_omp_reduction_non_addressable_expression : Error<
1006510066
"expected addressable reduction item for the task-based directives">;
1006610067
def err_omp_reduction_with_nogroup : Error<
@@ -10100,6 +10101,19 @@ def err_omp_depobj_single_clause_expected : Error<
1010010101
"exactly one of 'depend', 'destroy', or 'update' clauses is expected">;
1010110102
def err_omp_scan_single_clause_expected : Error<
1010210103
"exactly one of 'inclusive' or 'exclusive' clauses is expected">;
10104+
def err_omp_inclusive_exclusive_not_reduction : Error<
10105+
"the list item must appear in 'reduction' clause with the 'inscan' modifier "
10106+
"of the parent directive">;
10107+
def err_omp_reduction_not_inclusive_exclusive : Error<
10108+
"the inscan reduction list item must appear as a list item in an 'inclusive' or"
10109+
" 'exclusive' clause on an inner 'omp scan' directive">;
10110+
def err_omp_wrong_inscan_reduction : Error<
10111+
"'inscan' modifier can be used only in 'omp for', 'omp simd', 'omp for simd',"
10112+
" 'omp parallel for', or 'omp parallel for simd' directive">;
10113+
def err_omp_inscan_reduction_expected : Error<
10114+
"expected 'reduction' clause with the 'inscan' modifier">;
10115+
def note_omp_previous_inscan_reduction : Note<
10116+
"'reduction' clause with 'inscan' modifier is used here">;
1010310117
def err_omp_expected_predefined_allocator : Error<
1010410118
"expected one of the predefined allocators for the variables with the static "
1010510119
"storage: 'omp_default_mem_alloc', 'omp_large_cap_mem_alloc', "

clang/include/clang/Basic/OpenMPKinds.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1112,6 +1112,7 @@ OPENMP_DEPOBJ_CLAUSE(update)
11121112

11131113
// Modifiers for 'reduction' clause.
11141114
OPENMP_REDUCTION_MODIFIER(default)
1115+
OPENMP_REDUCTION_MODIFIER(inscan)
11151116

11161117
#undef OPENMP_REDUCTION_MODIFIER
11171118
#undef OPENMP_SCAN_CLAUSE

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 134 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,14 +62,15 @@ class DSAStackTy {
6262
struct DSAVarData {
6363
OpenMPDirectiveKind DKind = OMPD_unknown;
6464
OpenMPClauseKind CKind = OMPC_unknown;
65+
unsigned Modifier = 0;
6566
const Expr *RefExpr = nullptr;
6667
DeclRefExpr *PrivateCopy = nullptr;
6768
SourceLocation ImplicitDSALoc;
6869
DSAVarData() = default;
6970
DSAVarData(OpenMPDirectiveKind DKind, OpenMPClauseKind CKind,
7071
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),
7374
PrivateCopy(PrivateCopy), ImplicitDSALoc(ImplicitDSALoc) {}
7475
};
7576
using OperatorOffsetTy =
@@ -80,6 +81,7 @@ class DSAStackTy {
8081
private:
8182
struct DSAInfo {
8283
OpenMPClauseKind Attributes = OMPC_unknown;
84+
unsigned Modifier = 0;
8385
/// Pointer to a reference expression and a flag which shows that the
8486
/// variable is marked as lastprivate(true) or not (false).
8587
llvm::PointerIntPair<const Expr *, 1, bool> RefExpr;
@@ -164,6 +166,8 @@ class DSAStackTy {
164166
/// List of globals marked as declare target link in this target region
165167
/// (isOpenMPTargetExecutionDirective(Directive) == true).
166168
llvm::SmallVector<DeclRefExpr *, 4> DeclareTargetLinkVarDecls;
169+
/// List of decls used in inclusive/exclusive clauses of the scan directive.
170+
llvm::DenseSet<CanonicalDeclPtr<Decl>> UsedInScanDirective;
167171
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
168172
Scope *CurScope, SourceLocation Loc)
169173
: Directive(DKind), DirectiveName(Name), CurScope(CurScope),
@@ -469,9 +473,21 @@ class DSAStackTy {
469473
/// parent directive.
470474
const ValueDecl *getParentLoopControlVariable(unsigned I) const;
471475

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+
472488
/// Adds explicit data sharing attribute to the specified declaration.
473489
void addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
474-
DeclRefExpr *PrivateCopy = nullptr);
490+
DeclRefExpr *PrivateCopy = nullptr, unsigned Modifier = 0);
475491

476492
/// Adds additional information for the reduction items with the reduction id
477493
/// represented as an operator.
@@ -1079,6 +1095,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(const_iterator &Iter,
10791095
DVar.PrivateCopy = Data.PrivateCopy;
10801096
DVar.CKind = Data.Attributes;
10811097
DVar.ImplicitDSALoc = Iter->DefaultAttrLoc;
1098+
DVar.Modifier = Data.Modifier;
10821099
return DVar;
10831100
}
10841101

@@ -1226,19 +1243,21 @@ const ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) const {
12261243
}
12271244

12281245
void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
1229-
DeclRefExpr *PrivateCopy) {
1246+
DeclRefExpr *PrivateCopy, unsigned Modifier) {
12301247
D = getCanonicalDecl(D);
12311248
if (A == OMPC_threadprivate) {
12321249
DSAInfo &Data = Threadprivates[D];
12331250
Data.Attributes = A;
12341251
Data.RefExpr.setPointer(E);
12351252
Data.PrivateCopy = nullptr;
1253+
Data.Modifier = Modifier;
12361254
} else {
12371255
DSAInfo &Data = getTopOfStack().SharingMap[D];
12381256
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
12391257
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
12401258
(A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) ||
12411259
(isLoopControlVariable(D).first && A == OMPC_private));
1260+
Data.Modifier = Modifier;
12421261
if (A == OMPC_lastprivate && Data.Attributes == OMPC_firstprivate) {
12431262
Data.RefExpr.setInt(/*IntVal=*/true);
12441263
return;
@@ -1250,6 +1269,7 @@ void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OpenMPClauseKind A,
12501269
Data.PrivateCopy = PrivateCopy;
12511270
if (PrivateCopy) {
12521271
DSAInfo &Data = getTopOfStack().SharingMap[PrivateCopy->getDecl()];
1272+
Data.Modifier = Modifier;
12531273
Data.Attributes = A;
12541274
Data.RefExpr.setPointerAndInt(PrivateCopy, IsLastprivate);
12551275
Data.PrivateCopy = nullptr;
@@ -1355,7 +1375,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
13551375
"set.");
13561376
TaskgroupDescriptor = I->TaskgroupReductionRef;
13571377
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
1358-
Data.PrivateCopy, I->DefaultAttrLoc);
1378+
Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0);
13591379
}
13601380
return DSAVarData();
13611381
}
@@ -1380,7 +1400,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopMostTaskgroupReductionData(
13801400
"set.");
13811401
TaskgroupDescriptor = I->TaskgroupReductionRef;
13821402
return DSAVarData(OMPD_taskgroup, OMPC_reduction, Data.RefExpr.getPointer(),
1383-
Data.PrivateCopy, I->DefaultAttrLoc);
1403+
Data.PrivateCopy, I->DefaultAttrLoc, /*Modifier=*/0);
13841404
}
13851405
return DSAVarData();
13861406
}
@@ -1455,6 +1475,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
14551475
if (TI != Threadprivates.end()) {
14561476
DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
14571477
DVar.CKind = OMPC_threadprivate;
1478+
DVar.Modifier = TI->getSecond().Modifier;
14581479
return DVar;
14591480
}
14601481
if (VD && VD->hasAttr<OMPThreadPrivateDeclAttr>()) {
@@ -1546,6 +1567,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
15461567
DVar.CKind = Data.Attributes;
15471568
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
15481569
DVar.DKind = I->Directive;
1570+
DVar.Modifier = Data.Modifier;
15491571
return DVar;
15501572
}
15511573

@@ -1592,6 +1614,7 @@ const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
15921614
DVar.CKind = Data.Attributes;
15931615
DVar.ImplicitDSALoc = I->DefaultAttrLoc;
15941616
DVar.DKind = I->Directive;
1617+
DVar.Modifier = Data.Modifier;
15951618
}
15961619

15971620
return DVar;
@@ -2299,11 +2322,64 @@ void Sema::EndOpenMPClause() {
22992322
DSAStack->setClauseParsingMode(/*K=*/OMPC_unknown);
23002323
}
23012324

2302-
static void checkAllocateClauses(Sema &S, DSAStackTy *Stack,
2303-
ArrayRef<OMPClause *> Clauses);
23042325
static std::pair<ValueDecl *, bool>
23052326
getPrivateItem(Sema &S, Expr *&RefExpr, SourceLocation &ELoc,
23062327
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);
23072383
static DeclRefExpr *buildCapture(Sema &S, ValueDecl *D, Expr *CaptureExpr,
23082384
bool WithInit);
23092385

@@ -2380,6 +2456,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) {
23802456
// Check allocate clauses.
23812457
if (!CurContext->isDependentContext())
23822458
checkAllocateClauses(*this, DSAStack, D->clauses());
2459+
checkReductionClauses(*this, DSAStack, D->clauses());
23832460
}
23842461

23852462
DSAStack->pop();
@@ -4177,7 +4254,7 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
41774254
if (ParentRegion == OMPD_unknown &&
41784255
!isOpenMPNestingTeamsDirective(CurrentRegion) &&
41794256
CurrentRegion != OMPD_cancellation_point &&
4180-
CurrentRegion != OMPD_cancel)
4257+
CurrentRegion != OMPD_cancel && CurrentRegion != OMPD_scan)
41814258
return false;
41824259
if (CurrentRegion == OMPD_cancellation_point ||
41834260
CurrentRegion == OMPD_cancel) {
@@ -4298,7 +4375,8 @@ static bool checkNestingOfRegions(Sema &SemaRef, const DSAStackTy *Stack,
42984375
NestingProhibited =
42994376
SemaRef.LangOpts.OpenMP < 50 ||
43004377
(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);
43024380
OrphanSeen = ParentRegion == OMPD_unknown;
43034381
Recommend = ShouldBeInLoopSimdRegion;
43044382
}
@@ -13971,9 +14049,11 @@ struct ReductionData {
1397114049
SmallVector<Decl *, 4> ExprCaptures;
1397214050
/// List of postupdate expressions.
1397314051
SmallVector<Expr *, 4> ExprPostUpdates;
14052+
/// Reduction modifier.
14053+
unsigned RedModifier = 0;
1397414054
ReductionData() = delete;
1397514055
/// Reserves required memory for the reduction data.
13976-
ReductionData(unsigned Size) {
14056+
ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
1397714057
Vars.reserve(Size);
1397814058
Privates.reserve(Size);
1397914059
LHSs.reserve(Size);
@@ -14691,7 +14771,8 @@ static bool actOnOMPReductionKindClause(
1469114771
}
1469214772
// All reduction items are still marked as reduction (to do not increase
1469314773
// code base size).
14694-
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref);
14774+
Stack->addDSA(D, RefExpr->IgnoreParens(), OMPC_reduction, Ref,
14775+
RD.RedModifier);
1469514776
if (CurrDir == OMPD_taskgroup) {
1469614777
if (DeclareReductionRef.isUsable())
1469714778
Stack->addTaskgroupReductionData(D, ReductionIdRange,
@@ -14718,8 +14799,22 @@ OMPClause *Sema::ActOnOpenMPReductionClause(
1471814799
<< getOpenMPClauseName(OMPC_reduction);
1471914800
return nullptr;
1472014801
}
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+
}
1472114816

14722-
ReductionData RD(VarList.size());
14817+
ReductionData RD(VarList.size(), Modifier);
1472314818
if (actOnOMPReductionKindClause(*this, DSAStack, OMPC_reduction, VarList,
1472414819
StartLoc, LParenLoc, ColonLoc, EndLoc,
1472514820
ReductionIdScopeSpec, ReductionId,
@@ -18021,6 +18116,19 @@ OMPClause *Sema::ActOnOpenMPInclusiveClause(ArrayRef<Expr *> VarList,
1802118116
if (!D)
1802218117
continue;
1802318118

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);
1802418132
Vars.push_back(RefExpr);
1802518133
}
1802618134

@@ -18049,6 +18157,19 @@ OMPClause *Sema::ActOnOpenMPExclusiveClause(ArrayRef<Expr *> VarList,
1804918157
if (!D)
1805018158
continue;
1805118159

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);
1805218173
Vars.push_back(RefExpr);
1805318174
}
1805418175

0 commit comments

Comments
 (0)