Skip to content

Commit 118e8a7

Browse files
committed
Support data-sharings deduced from depend clause
Closes llvm#8
1 parent 9cdc094 commit 118e8a7

File tree

6 files changed

+185
-1
lines changed

6 files changed

+185
-1
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9494,6 +9494,8 @@ def err_oss_depend_weak_required : Error<
94949494
"expected 'weak' clause">;
94959495
def err_oss_wrong_dsa : Error<
94969496
"%0 variable cannot be %1">;
9497+
def err_oss_mismatch_depend_dsa : Error<
9498+
"the data-sharing '%0' conflicts with '%1' required by the dependency">;
94979499

94989500
def err_oss_expected_addressable_lvalue_or_array_item : Error<
94999501
"expected addressable lvalue expression, array element or array section">;

clang/include/clang/Sema/Sema.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9306,6 +9306,11 @@ class Sema {
93069306
/// Called on end of data sharing attribute block.
93079307
void EndOmpSsDSABlock(Stmt *CurDirective);
93089308

9309+
// Check if there are conflicts between depend() and other DSA clauses
9310+
// This must happen before parsing the statement (if any) so child tasks
9311+
// can see DSA derived from 'depend' clauses
9312+
void ActOnOmpSsAfterClauseGathering(ArrayRef<OSSClause *> Clauses);
9313+
93099314
StmtResult ActOnOmpSsExecutableDirective(ArrayRef<OSSClause *> Clauses,
93109315
OmpSsDirectiveKind Kind, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc);
93119316

clang/lib/Parse/ParseOmpSs.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ StmtResult Parser::ParseOmpSsDeclarativeOrExecutableDirective(
9191
// Consume final annot_pragma_openmp_end.
9292
ConsumeAnnotationToken();
9393

94+
Actions.ActOnOmpSsAfterClauseGathering(Clauses);
95+
9496
StmtResult AssociatedStmt;
9597
if (HasAssociatedStatement) {
9698
AssociatedStmt = (Sema::CompoundScopeRAII(Actions), ParseStatement());

clang/lib/Sema/SemaOmpSs.cpp

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,79 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
357357
DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, Stmt *CS)
358358
: Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {}
359359
};
360+
361+
class OSSClauseDSAChecker final : public StmtVisitor<OSSClauseDSAChecker, void> {
362+
DSAStackTy *Stack;
363+
Sema &SemaRef;
364+
bool ErrorFound = false;
365+
public:
366+
void VisitDeclRefExpr(DeclRefExpr *E) {
367+
if (E->isTypeDependent() || E->isValueDependent() ||
368+
E->containsUnexpandedParameterPack() || E->isInstantiationDependent())
369+
return;
370+
371+
if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) {
372+
VD = VD->getCanonicalDecl();
373+
// inout(x) | shared(x) | int x;
374+
// inout(p[i]) | firstprivate(p) | int *p;
375+
// inout(a[i]) | shared(a) | int a[N];
376+
// inout(*p)/inout(p[0]) | firstprivate(p) | int *p;
377+
// inout(s.x) | shared(s) | struct S s;
378+
// inout(ps->x) | firstprivate(ps) | struct S *ps;
379+
OmpSsClauseKind VKind = OSSC_shared;
380+
if (VD->getType()->isPointerType())
381+
VKind = OSSC_firstprivate;
382+
383+
SourceLocation ELoc = E->getExprLoc();
384+
SourceRange ERange = E->getSourceRange();
385+
386+
DSAStackTy::DSAVarData DVarCurrent = Stack->getCurrentDSA(VD);
387+
switch (DVarCurrent.CKind) {
388+
case OSSC_shared:
389+
if (VKind == OSSC_private || VKind == OSSC_firstprivate) {
390+
ErrorFound = true;
391+
SemaRef.Diag(ELoc, diag::err_oss_mismatch_depend_dsa)
392+
<< getOmpSsClauseName(DVarCurrent.CKind)
393+
<< getOmpSsClauseName(VKind) << ERange;
394+
}
395+
break;
396+
case OSSC_private:
397+
case OSSC_firstprivate:
398+
if (VKind == OSSC_shared) {
399+
ErrorFound = true;
400+
SemaRef.Diag(ELoc, diag::err_oss_mismatch_depend_dsa)
401+
<< getOmpSsClauseName(DVarCurrent.CKind)
402+
<< getOmpSsClauseName(VKind) << ERange;
403+
}
404+
break;
405+
default:
406+
// OK: no DSA explicit, record DSA as explicit, but do not
407+
// make a node for it
408+
Stack->addDSA(VD, E, VKind, false);
409+
break;
410+
}
411+
}
412+
}
413+
414+
void VisitOSSDepend(OSSDependClause *Clause) {
415+
for (Stmt *Child : Clause->children()) {
416+
if (Child)
417+
Visit(Child);
418+
}
419+
}
420+
421+
void VisitStmt(Stmt *S) {
422+
for (Stmt *C : S->children()) {
423+
if (C)
424+
Visit(C);
425+
}
426+
}
427+
428+
bool isErrorFound() const { return ErrorFound; }
429+
430+
OSSClauseDSAChecker(DSAStackTy *S, Sema &SemaRef)
431+
: Stack(S), SemaRef(SemaRef), ErrorFound(false) {}
432+
};
360433
} // namespace
361434

362435
void Sema::InitDataSharingAttributesStackOmpSs() {
@@ -400,10 +473,19 @@ getListOfPossibleValues(OmpSsClauseKind K, unsigned First, unsigned Last,
400473
return Out.str();
401474
}
402475

476+
void Sema::ActOnOmpSsAfterClauseGathering(ArrayRef<OSSClause *> Clauses) {
477+
OSSClauseDSAChecker OSSDependChecker(DSAStack, *this);
478+
for (auto *Clause : Clauses) {
479+
if (Clause->getClauseKind() == OSSC_depend)
480+
OSSDependChecker.VisitOSSDepend(cast<OSSDependClause> (Clause));
481+
}
482+
}
483+
403484
StmtResult Sema::ActOnOmpSsExecutableDirective(ArrayRef<OSSClause *> Clauses,
404485
OmpSsDirectiveKind Kind, Stmt *AStmt, SourceLocation StartLoc, SourceLocation EndLoc) {
405486

406487
bool ErrorFound = false;
488+
407489
llvm::SmallVector<OSSClause *, 8> ClausesWithImplicit;
408490
ClausesWithImplicit.append(Clauses.begin(), Clauses.end());
409491
if (AStmt) {
@@ -412,7 +494,7 @@ StmtResult Sema::ActOnOmpSsExecutableDirective(ArrayRef<OSSClause *> Clauses,
412494
Stmt *S = AStmt;
413495
DSAChecker.Visit(S);
414496
if (DSAChecker.isErrorFound())
415-
return StmtError();
497+
ErrorFound = true;
416498

417499
SmallVector<Expr *, 4> ImplicitShared(
418500
DSAChecker.getImplicitShared().begin(),

clang/test/OmpSs/task_depend_ast.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,71 @@ int main() {
1919
// CHECK-NEXT: UnaryOperator {{[a-z0-9]+}} <col:{{[0-9]+}}, col:{{[0-9]+}}> 'int' lvalue prefix '*' cannot overflow
2020
// CHECK-NEXT: ImplicitCastExpr {{[a-z0-9]+}} <col:{{[0-9]+}}> 'int *' <LValueToRValue>
2121
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <col:{{[0-9]+}}> 'int *' lvalue Var {{[a-z0-9]+}} 'c' 'int *
22+
23+
int *p;
24+
int foo() {
25+
#pragma oss task depend(inout: *p)
26+
{
27+
#pragma oss task
28+
{
29+
*p = 0;
30+
}
31+
}
32+
return 0;
33+
}
34+
35+
// CHECK: OSSTaskDirective {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
36+
// CHECK-NEXT: OSSDependClause {{[a-z0-9]+}} <col:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
37+
// CHECK-NEXT: UnaryOperator {{[a-z0-9]+}} <col:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}> 'int' lvalue prefix '*' cannot overflow
38+
// CHECK-NEXT: ImplicitCastExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int *' <LValueToRValue>
39+
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int *' lvalue Var {{[a-z0-9]+}} 'p' 'int *'
40+
// CHECK-NEXT: CompoundStmt {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, line:{{[a-z0-9]+}}:{{[a-z0-9]+}}>
41+
// CHECK-NEXT: OSSTaskDirective {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
42+
// CHECK-NEXT: OSSFirstprivateClause {{[a-z0-9]+}} <<invalid sloc>> <implicit>
43+
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}> 'int *' lvalue Var {{[a-z0-9]+}} 'p' 'int *'
44+
45+
int array[5];
46+
int foo1() {
47+
#pragma oss task depend(inout: array[2])
48+
{
49+
#pragma oss task
50+
{
51+
array[2] = 0;
52+
}
53+
}
54+
return 0;
55+
}
56+
57+
// CHECK: OSSTaskDirective {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
58+
// CHECK-NEXT: OSSDependClause {{[a-z0-9]+}} <col:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
59+
// CHECK-NEXT: ArraySubscriptExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}> 'int' lvalue
60+
// CHECK-NEXT: ImplicitCastExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int *' <ArrayToPointerDecay>
61+
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int [5]' lvalue Var {{[a-z0-9]+}} 'array' 'int [5]'
62+
// CHECK-NEXT: IntegerLiteral {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int' 2
63+
// CHECK-NEXT: CompoundStmt {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, line:{{[a-z0-9]+}}:{{[a-z0-9]+}}>
64+
// CHECK-NEXT: OSSTaskDirective {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
65+
// CHECK-NEXT: OSSSharedClause {{[a-z0-9]+}} <<invalid sloc>> <implicit>
66+
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}> 'int [5]' lvalue Var {{[a-z0-9]+}} 'array' 'int [5]'
67+
68+
int foo2() {
69+
int array[5];
70+
#pragma oss task depend(inout: array[2])
71+
{
72+
#pragma oss task
73+
{
74+
array[2] = 0;
75+
}
76+
}
77+
return 0;
78+
}
79+
80+
// CHECK: OSSTaskDirective {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
81+
// CHECK-NEXT: OSSDependClause {{[a-z0-9]+}} <col:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
82+
// CHECK-NEXT: ArraySubscriptExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}> 'int' lvalue
83+
// CHECK-NEXT: ImplicitCastExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int *' <ArrayToPointerDecay>
84+
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int [5]' lvalue Var {{[a-z0-9]+}} 'array' 'int [5]'
85+
// CHECK-NEXT: IntegerLiteral {{[a-z0-9]+}} <col:{{[a-z0-9]+}}> 'int' 2
86+
// CHECK-NEXT: CompoundStmt {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, line:{{[a-z0-9]+}}:{{[a-z0-9]+}}>
87+
// CHECK-NEXT: OSSTaskDirective {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}, col:{{[a-z0-9]+}}>
88+
// CHECK-NEXT: OSSFirstprivateClause {{[a-z0-9]+}} <<invalid sloc>> <implicit>
89+
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <line:{{[a-z0-9]+}}:{{[a-z0-9]+}}> 'int [5]' lvalue Var {{[a-z0-9]+}} 'array' 'int [5]'
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
// RUN: %clang_cc1 -verify -fompss-2 -ferror-limit 100 -o - -std=c++11 %s
2+
3+
struct S {
4+
int x;
5+
};
6+
7+
int array[5];
8+
9+
int main() {
10+
S s;
11+
S *ps;
12+
13+
int i;
14+
int *p;
15+
#pragma oss task private(i) depend(inout: i) // expected-error {{the data-sharing 'private' conflicts with 'shared' required by the dependency}}
16+
#pragma oss task depend(inout: i) private(i) // expected-error {{the data-sharing 'private' conflicts with 'shared' required by the dependency}}
17+
#pragma oss task firstprivate(i) depend(inout: i) // expected-error {{the data-sharing 'firstprivate' conflicts with 'shared' required by the dependency}}
18+
#pragma oss task shared(p) depend(inout: p[2]) // expected-error {{the data-sharing 'shared' conflicts with 'firstprivate' required by the dependency}}
19+
#pragma oss task shared(p) depend(inout: *p) // expected-error {{the data-sharing 'shared' conflicts with 'firstprivate' required by the dependency}}
20+
#pragma oss task firstprivate(array) depend(inout: array[2]) // expected-error {{the data-sharing 'firstprivate' conflicts with 'shared' required by the dependency}}
21+
#pragma oss task firstprivate(s) depend(inout: s.x) // expected-error {{the data-sharing 'firstprivate' conflicts with 'shared' required by the dependency}}
22+
#pragma oss task shared(ps) depend(inout: ps->x) // expected-error {{the data-sharing 'shared' conflicts with 'firstprivate' required by the dependency}}
23+
{}
24+
}
25+

0 commit comments

Comments
 (0)