Skip to content

Commit 83a4a53

Browse files
committed
Allow promotion from implicit firstprivate to implicit shared or shared in depend clauses
OSSDependDSAChecker is now used to gather implicit DSAs for all depend clauses, and not one by one as before. Fixes llvm#27
1 parent 4d6e93e commit 83a4a53

File tree

5 files changed

+83
-65
lines changed

5 files changed

+83
-65
lines changed

clang/lib/Sema/SemaOmpSs.cpp

Lines changed: 75 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ class DSAStackTy {
4747
OmpSsClauseKind CKind = OSSC_unknown;
4848
const Expr *RefExpr = nullptr;
4949
bool Ignore = false;
50+
bool Implicit = false;
5051
DSAVarData() = default;
5152
DSAVarData(OmpSsDirectiveKind DKind, OmpSsClauseKind CKind,
5253
const Expr *RefExpr, bool Ignore)
@@ -59,6 +60,7 @@ class DSAStackTy {
5960
OmpSsClauseKind Attributes = OSSC_unknown;
6061
const Expr * RefExpr;
6162
bool Ignore = false;
63+
bool Implicit = false;
6264
};
6365
using DeclSAMapTy = llvm::SmallDenseMap<const ValueDecl *, DSAInfo, 8>;
6466

@@ -106,7 +108,8 @@ class DSAStackTy {
106108
}
107109

108110
/// Adds explicit data sharing attribute to the specified declaration.
109-
void addDSA(const ValueDecl *D, const Expr *E, OmpSsClauseKind A, bool Ignore=false);
111+
void addDSA(const ValueDecl *D, const Expr *E, OmpSsClauseKind A,
112+
bool Ignore, bool Implicit);
110113

111114
/// Returns data sharing attributes from top of the stack for the
112115
/// specified declaration.
@@ -180,20 +183,23 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(iterator &Iter,
180183
const DSAInfo &Data = Iter->SharingMap.lookup(D);
181184
DVar.RefExpr = Data.RefExpr;
182185
DVar.Ignore = Data.Ignore;
186+
DVar.Implicit = Data.Implicit;
183187
DVar.CKind = Data.Attributes;
184188
return DVar;
185189
}
186190

187191
return DVar;
188192
}
189193

190-
void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OmpSsClauseKind A, bool Ignore) {
194+
void DSAStackTy::addDSA(const ValueDecl *D, const Expr *E, OmpSsClauseKind A,
195+
bool Ignore, bool Implicit) {
191196
D = getCanonicalDecl(D);
192197
assert(!isStackEmpty() && "Data-sharing attributes stack is empty");
193198
DSAInfo &Data = Stack.back().SharingMap[D];
194199
Data.Attributes = A;
195200
Data.RefExpr = E;
196201
Data.Ignore = Ignore;
202+
Data.Implicit = Implicit;
197203
}
198204

199205
const DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D,
@@ -336,13 +342,13 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
336342
if (isOmpSsTaskingDirective(DKind))
337343
ImplicitShared.push_back(E);
338344
// Record DSA as Ignored to avoid making the same node again
339-
Stack->addDSA(VD, E, OSSC_shared, /*Ignore=*/true);
345+
Stack->addDSA(VD, E, OSSC_shared, /*Ignore=*/true, /*Implicit=*/true);
340346
break;
341347
case DSA_none:
342348
if (!DVarCurrent.Ignore) {
343349
SemaRef.Diag(E->getExprLoc(), diag::err_oss_not_defined_dsa_when_default_none) << E->getDecl();
344350
// Record DSA as ignored to diagnostic only once
345-
Stack->addDSA(VD, E, OSSC_unknown, /*Ignore=*/true);
351+
Stack->addDSA(VD, E, OSSC_unknown, /*Ignore=*/true, /*Implicit=*/true);
346352
}
347353
break;
348354
case DSA_unspecified:
@@ -356,7 +362,7 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
356362
ImplicitFirstprivate.push_back(E);
357363

358364
// Record DSA as Ignored to avoid making the same node again
359-
Stack->addDSA(VD, E, OSSC_firstprivate, /*Ignore=*/true);
365+
Stack->addDSA(VD, E, OSSC_firstprivate, /*Ignore=*/true, /*Implicit=*/true);
360366
} else {
361367
// If no default clause is present and the variable was shared/global
362368
// in the context encountering the construct, the variable will be shared.
@@ -366,7 +372,7 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
366372
ImplicitShared.push_back(E);
367373

368374
// Record DSA as Ignored to avoid making the same node again
369-
Stack->addDSA(VD, E, OSSC_shared, /*Ignore=*/true);
375+
Stack->addDSA(VD, E, OSSC_shared, /*Ignore=*/true, /*Implicit=*/true);
370376
}
371377
}
372378
}
@@ -479,6 +485,10 @@ class OSSClauseDSAChecker final : public StmtVisitor<OSSClauseDSAChecker, void>
479485
DSAStackTy::DSAVarData DVarCurrent = Stack->getCurrentDSA(VD);
480486
switch (DVarCurrent.CKind) {
481487
case OSSC_shared:
488+
if (IsArraySubscriptIdx) {
489+
// shared(n) in(array[n])
490+
break;
491+
}
482492
if (VKind == OSSC_private || VKind == OSSC_firstprivate) {
483493
ErrorFound = true;
484494
SemaRef.Diag(ELoc, diag::err_oss_mismatch_depend_dsa)
@@ -489,28 +499,34 @@ class OSSClauseDSAChecker final : public StmtVisitor<OSSClauseDSAChecker, void>
489499
case OSSC_private:
490500
case OSSC_firstprivate:
491501
if (VKind == OSSC_shared) {
492-
ErrorFound = true;
493-
SemaRef.Diag(ELoc, diag::err_oss_mismatch_depend_dsa)
494-
<< getOmpSsClauseName(DVarCurrent.CKind)
495-
<< getOmpSsClauseName(VKind) << ERange;
502+
if (DVarCurrent.Implicit) {
503+
// Promote Implicit firstprivate to Implicit shared
504+
auto It = ImplicitFirstprivate.begin();
505+
while (It != ImplicitFirstprivate.end()) {
506+
if (*It == DVarCurrent.RefExpr) break;
507+
++It;
508+
}
509+
assert(It != ImplicitFirstprivate.end());
510+
ImplicitFirstprivate.erase(It);
511+
512+
ImplicitShared.push_back(E);
513+
// Rewrite DSA
514+
Stack->addDSA(VD, E, VKind, /*Ignore=*/false, /*Implicit=*/true);
515+
} else {
516+
ErrorFound = true;
517+
SemaRef.Diag(ELoc, diag::err_oss_mismatch_depend_dsa)
518+
<< getOmpSsClauseName(DVarCurrent.CKind)
519+
<< getOmpSsClauseName(VKind) << ERange;
520+
}
496521
}
497522
break;
498523
case OSSC_unknown:
499-
// No DSA explicit
500-
if (Stack->getCurrentDefaultDataSharingAttributtes() == DSA_none) {
501-
// KO: but default(none)
502-
// Record DSA as ignored
503-
SemaRef.Diag(ELoc, diag::err_oss_not_defined_dsa_when_default_none) << E->getDecl();
504-
Stack->addDSA(VD, E, OSSC_unknown, /*Ignore=*/true);
505-
} else {
506-
// OK: record DSA as explicit
507-
if (VKind == OSSC_shared)
508-
ImplicitShared.push_back(E);
509-
if (VKind == OSSC_firstprivate)
510-
ImplicitFirstprivate.push_back(E);
524+
if (VKind == OSSC_shared)
525+
ImplicitShared.push_back(E);
526+
if (VKind == OSSC_firstprivate)
527+
ImplicitFirstprivate.push_back(E);
511528

512-
Stack->addDSA(VD, E, VKind);
513-
}
529+
Stack->addDSA(VD, E, VKind, /*Ignore=*/false, /*Implicit=*/true);
514530

515531
break;
516532
default:
@@ -595,46 +611,47 @@ void Sema::ActOnOmpSsAfterClauseGathering(SmallVectorImpl<OSSClause *>& Clauses)
595611

596612
bool ErrorFound = false;
597613

614+
OSSClauseDSAChecker OSSDependChecker(DSAStack, *this);
598615
for (auto *Clause : Clauses) {
599-
OSSClauseDSAChecker OSSDependChecker(DSAStack, *this);
600616
if (isa<OSSDependClause>(Clause)) {
601617
OSSDependChecker.VisitOSSDepend(cast<OSSDependClause> (Clause));
618+
}
619+
// FIXME: how to handle an error?
620+
if (OSSDependChecker.isErrorFound())
621+
ErrorFound = true;
622+
}
602623

603-
if (OSSDependChecker.isErrorFound())
604-
ErrorFound = true;
605624

606-
SmallVector<Expr *, 4> ImplicitShared(
607-
OSSDependChecker.getImplicitShared().begin(),
608-
OSSDependChecker.getImplicitShared().end());
625+
SmallVector<Expr *, 4> ImplicitShared(
626+
OSSDependChecker.getImplicitShared().begin(),
627+
OSSDependChecker.getImplicitShared().end());
609628

610-
SmallVector<Expr *, 4> ImplicitFirstprivate(
611-
OSSDependChecker.getImplicitFirstprivate().begin(),
612-
OSSDependChecker.getImplicitFirstprivate().end());
629+
SmallVector<Expr *, 4> ImplicitFirstprivate(
630+
OSSDependChecker.getImplicitFirstprivate().begin(),
631+
OSSDependChecker.getImplicitFirstprivate().end());
613632

614-
if (!ImplicitShared.empty()) {
615-
if (OSSClause *Implicit = ActOnOmpSsSharedClause(
616-
ImplicitShared, SourceLocation(), SourceLocation(),
617-
SourceLocation(), /*isImplicit=*/true)) {
618-
Clauses.push_back(Implicit);
619-
if (cast<OSSSharedClause>(Implicit)->varlist_size() != ImplicitShared.size())
620-
ErrorFound = true;
633+
if (!ImplicitShared.empty()) {
634+
if (OSSClause *Implicit = ActOnOmpSsSharedClause(
635+
ImplicitShared, SourceLocation(), SourceLocation(),
636+
SourceLocation(), /*isImplicit=*/true)) {
637+
Clauses.push_back(Implicit);
638+
if (cast<OSSSharedClause>(Implicit)->varlist_size() != ImplicitShared.size())
639+
ErrorFound = true;
621640

622-
} else {
623-
ErrorFound = true;
624-
}
625-
}
641+
} else {
642+
ErrorFound = true;
643+
}
644+
}
626645

627-
if (!ImplicitFirstprivate.empty()) {
628-
if (OSSClause *Implicit = ActOnOmpSsFirstprivateClause(
629-
ImplicitFirstprivate, SourceLocation(), SourceLocation(),
630-
SourceLocation())) {
631-
Clauses.push_back(Implicit);
632-
if (cast<OSSFirstprivateClause>(Implicit)->varlist_size() != ImplicitFirstprivate.size())
633-
ErrorFound = true;
634-
} else {
635-
ErrorFound = true;
636-
}
637-
}
646+
if (!ImplicitFirstprivate.empty()) {
647+
if (OSSClause *Implicit = ActOnOmpSsFirstprivateClause(
648+
ImplicitFirstprivate, SourceLocation(), SourceLocation(),
649+
SourceLocation())) {
650+
Clauses.push_back(Implicit);
651+
if (cast<OSSFirstprivateClause>(Implicit)->varlist_size() != ImplicitFirstprivate.size())
652+
ErrorFound = true;
653+
} else {
654+
ErrorFound = true;
638655
}
639656
}
640657
}
@@ -1017,7 +1034,7 @@ Sema::ActOnOmpSsSharedClause(ArrayRef<Expr *> Vars,
10171034
<< getOmpSsClauseName(OSSC_shared);
10181035
continue;
10191036
}
1020-
DSAStack->addDSA(D, RefExpr, OSSC_shared);
1037+
DSAStack->addDSA(D, RefExpr, OSSC_shared, /*Ignore=*/false, /*Implicit=*/false);
10211038
ClauseVars.push_back(RefExpr);
10221039
}
10231040

@@ -1055,7 +1072,7 @@ Sema::ActOnOmpSsPrivateClause(ArrayRef<Expr *> Vars,
10551072
<< getOmpSsClauseName(OSSC_private);
10561073
continue;
10571074
}
1058-
DSAStack->addDSA(D, RefExpr, OSSC_private);
1075+
DSAStack->addDSA(D, RefExpr, OSSC_private, /*Ignore=*/false, /*Implicit=*/false);
10591076
ClauseVars.push_back(RefExpr);
10601077
}
10611078

@@ -1093,7 +1110,7 @@ Sema::ActOnOmpSsFirstprivateClause(ArrayRef<Expr *> Vars,
10931110
<< getOmpSsClauseName(OSSC_firstprivate);
10941111
continue;
10951112
}
1096-
DSAStack->addDSA(D, RefExpr, OSSC_firstprivate);
1113+
DSAStack->addDSA(D, RefExpr, OSSC_firstprivate, /*Ignore=*/false, /*Implicit=*/false);
10971114
ClauseVars.push_back(RefExpr);
10981115
}
10991116

clang/test/OmpSs/AST/task_dep_dsa_duplicate.c

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,9 @@ void foo(int i, int j) {
2626
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:54> 'int' lvalue Var 0x{{[^ ]*}} 'global' 'int'
2727
// CHECK-NEXT: OSSSharedClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
2828
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:32> 'struct S':'struct S' lvalue Var 0x{{[^ ]*}} 's' 'struct S':'struct S'
29+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:54> 'int' lvalue Var 0x{{[^ ]*}} 'global' 'int'
2930
// CHECK-NEXT: OSSFirstprivateClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
3031
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:36> 'int' lvalue ParmVar 0x{{[^ ]*}} 'i' 'int'
3132
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:38> 'int' lvalue ParmVar 0x{{[^ ]*}} 'j' 'int'
32-
// CHECK-NEXT: OSSSharedClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
33-
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:54> 'int' lvalue Var 0x{{[^ ]*}} 'global' 'int'
3433

3534

clang/test/OmpSs/AST/task_depend.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -285,10 +285,10 @@ void foo6(int *p, int n) {
285285
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:25> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
286286
// CHECK-NEXT: OSSDependClause 0x{{[^ ]*}} <col:28, col:33> <oss syntax>
287287
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:32> 'int' lvalue ParmVar 0x{{[^ ]*}} 'n' 'int'
288-
// CHECK-NEXT: OSSFirstprivateClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
289-
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:25> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
290288
// CHECK-NEXT: OSSSharedClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
291289
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:32> 'int' lvalue ParmVar 0x{{[^ ]*}} 'n' 'int'
290+
// CHECK-NEXT: OSSFirstprivateClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
291+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:25> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
292292

293293
void foo7() {
294294
int array[10][10];

clang/test/OmpSs/Sema/task_default.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@ int main() {
88
#pragma oss task default(none) default(shared) // expected-error {{directive '#pragma oss task' cannot contain more than one 'default' clause}}
99
{}
1010
#pragma oss task default(none)
11-
#pragma oss task default(none) depend(in: x) // expected-error {{expected explicit data-sharing for 'x'}}
11+
#pragma oss task default(none) depend(in: x)
1212
{ ++x; ++x; } // expected-error {{expected explicit data-sharing for 'x'}}
1313
}

clang/test/OmpSs/Sema/task_depend_dsa_conflict.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,11 @@ void foo() {
2727
int array[10];
2828
int a[10];
2929
int i, j;
30-
#pragma oss task depend(in: array[a[i]], a[i]) // expected-error {{the data-sharing 'firstprivate' conflicts with 'shared' required by the dependency}}
30+
// Promotion implicit firstprivate to implicit shared
31+
#pragma oss task depend(in: array[a[i]], a[i])
3132
{}
32-
#pragma oss task depend(in: array[i+j]) shared(i) // expected-error {{the data-sharing 'shared' conflicts with 'firstprivate' required by the dependency}}
33+
// Promotion implicit firstprivate to shared
34+
#pragma oss task depend(in: array[i+j]) shared(i)
3335
{}
3436
}
3537

0 commit comments

Comments
 (0)