Skip to content

Commit 7cfbd73

Browse files
committed
Sema: Pointers are fp only if they're dereferenced. Other things:
- Fix implicit DSA assignment behavior implemented in 83a4a53 - Do not emit an error if exists a private DSA - Add missing AST dump in task_depend.c Fixes: llvm#31
1 parent 349357f commit 7cfbd73

File tree

6 files changed

+98
-30
lines changed

6 files changed

+98
-30
lines changed

clang/lib/Sema/SemaOmpSs.cpp

Lines changed: 57 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -419,38 +419,77 @@ class DSAAttrChecker final : public StmtVisitor<DSAAttrChecker, void> {
419419
: Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {}
420420
};
421421

422+
// OSSClauseDSAChecker gathers for each expression in a depend clause
423+
// all implicit data-sharings.
424+
//
425+
// To do so, we classify as firstprivate the base symbol if it's a pointer and is
426+
// dereferenced by a SubscriptExpr, MemberExpr or UnaryOperator.
427+
// Otherwise it's shared.
428+
//
429+
// At the same time, all symbols found inside a SubscriptExpr will be firstprivate.
430+
// NOTE: implicit DSA from other tasks are ignored
422431
class OSSClauseDSAChecker final : public StmtVisitor<OSSClauseDSAChecker, void> {
423432
DSAStackTy *Stack;
424433
Sema &SemaRef;
425434
bool ErrorFound = false;
426435
llvm::SmallVector<Expr *, 4> ImplicitFirstprivate;
427436
llvm::SmallVector<Expr *, 4> ImplicitShared;
428-
bool IsArraySubscriptIdx = false;
437+
// This is used to know we're inside a subscript expression
438+
size_t ArraySubscriptCnt = 0;
439+
// This is used to mark the innermost base symbol expression as:
440+
// *p, p[2], p[1:2], [2]p, s.x, s->x
441+
bool IsDerefMemberArrayBase = false;
429442
public:
430443

431444
void VisitOSSArrayShapingExpr(OSSArrayShapingExpr *E) {
445+
if (isa<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts()))
446+
IsDerefMemberArrayBase = true;
432447
Visit(E->getBase());
433-
IsArraySubscriptIdx = true;
448+
IsDerefMemberArrayBase = false;
449+
450+
ArraySubscriptCnt++;
434451
for (Stmt *S : E->getShapes())
435452
Visit(S);
436-
IsArraySubscriptIdx = false;
453+
ArraySubscriptCnt--;
437454
}
438455

439456
void VisitOSSArraySectionExpr(OSSArraySectionExpr *E) {
457+
if (isa<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts()))
458+
IsDerefMemberArrayBase = true;
440459
Visit(E->getBase());
441-
IsArraySubscriptIdx = true;
460+
IsDerefMemberArrayBase = false;
461+
462+
ArraySubscriptCnt++;
442463
if (E->getLowerBound())
443464
Visit(E->getLowerBound());
444465
if (E->getLengthUpper())
445466
Visit(E->getLengthUpper());
446-
IsArraySubscriptIdx = false;
467+
ArraySubscriptCnt--;
447468
}
448469

449470
void VisitArraySubscriptExpr(ArraySubscriptExpr *E) {
471+
if (isa<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts()))
472+
IsDerefMemberArrayBase = true;
450473
Visit(E->getBase());
451-
IsArraySubscriptIdx = true;
474+
IsDerefMemberArrayBase = false;
475+
476+
ArraySubscriptCnt++;
452477
Visit(E->getIdx());
453-
IsArraySubscriptIdx = false;
478+
ArraySubscriptCnt--;
479+
}
480+
481+
void VisitUnaryOperator(UnaryOperator *E) {
482+
if (isa<DeclRefExpr>(E->getSubExpr()->IgnoreParenImpCasts()))
483+
IsDerefMemberArrayBase = true;
484+
Visit(E->getSubExpr());
485+
IsDerefMemberArrayBase = false;
486+
}
487+
488+
void VisitMemberExpr(MemberExpr *E) {
489+
if (isa<DeclRefExpr>(E->getBase()->IgnoreParenImpCasts()))
490+
IsDerefMemberArrayBase = true;
491+
Visit(E->getBase());
492+
IsDerefMemberArrayBase = false;
454493
}
455494

456495
void VisitCXXThisExpr(CXXThisExpr *ThisE) {
@@ -474,9 +513,16 @@ class OSSClauseDSAChecker final : public StmtVisitor<OSSClauseDSAChecker, void>
474513
// inout(s.x) | shared(s) | struct S s;
475514
// inout(ps->x) | firstprivate(ps) | struct S *ps;
476515
OmpSsClauseKind VKind = OSSC_shared;
477-
if (VD->getType()->isPointerType())
516+
// FIXME?: There's an overlapping between IsDerefMemberArrayBase
517+
// and ArraySubscriptCnt
518+
// i.e
519+
// a[b[7]]
520+
// b will have ArraySubscriptCnt > 0
521+
// and IsDerefMemberArrayBase true
522+
// Check ArraySubscriptCnt first since is more restrictive
523+
if (ArraySubscriptCnt)
478524
VKind = OSSC_firstprivate;
479-
else if (IsArraySubscriptIdx)
525+
else if (VD->getType()->isPointerType() && IsDerefMemberArrayBase)
480526
VKind = OSSC_firstprivate;
481527

482528
SourceLocation ELoc = E->getExprLoc();
@@ -485,18 +531,10 @@ class OSSClauseDSAChecker final : public StmtVisitor<OSSClauseDSAChecker, void>
485531
DSAStackTy::DSAVarData DVarCurrent = Stack->getCurrentDSA(VD);
486532
switch (DVarCurrent.CKind) {
487533
case OSSC_shared:
488-
if (IsArraySubscriptIdx) {
489-
// shared(n) in(array[n])
490-
break;
491-
}
492-
if (VKind == OSSC_private || VKind == OSSC_firstprivate) {
493-
ErrorFound = true;
494-
SemaRef.Diag(ELoc, diag::err_oss_mismatch_depend_dsa)
495-
<< getOmpSsClauseName(DVarCurrent.CKind)
496-
<< getOmpSsClauseName(VKind) << ERange;
497-
}
534+
// Do nothing
498535
break;
499536
case OSSC_private:
537+
break;
500538
case OSSC_firstprivate:
501539
if (VKind == OSSC_shared) {
502540
if (DVarCurrent.Implicit) {

clang/test/OmpSs/AST/task_depend.c

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -286,13 +286,14 @@ void foo6(int *p, int n) {
286286
// CHECK-NEXT: OSSDependClause 0x{{[^ ]*}} <col:{{.*}}, col:{{.*}}> <oss syntax>
287287
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{.*}}> 'int' lvalue ParmVar 0x{{[^ ]*}} 'n' 'int'
288288
// CHECK-NEXT: OSSSharedClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
289-
// 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 *'
289+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{.*}}> 'int *' lvalue ParmVar 0x{{[^ ]*}} 'p' 'int *'
290+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{.*}}> 'int' lvalue ParmVar 0x{{[^ ]*}} 'n' 'int'
292291

293292
void foo7() {
294293
int array[10][10];
295294
int a;
295+
int barr[5];
296+
int carr[5];
296297
#pragma oss task out(array[0 ; 5])
297298
{}
298299
#pragma oss task out(array[ ; a])
@@ -301,6 +302,8 @@ void foo7() {
301302
{}
302303
#pragma oss task out(array[ ; ][ ; ])
303304
{}
305+
#pragma oss task out(array[barr[4] ; carr[5]])
306+
{}
304307
}
305308

306309
// CHECK: OSSTaskDirective 0x{{[^ ]*}} <line:{{.*}}:{{.*}}, col:{{.*}}>
@@ -349,4 +352,25 @@ void foo7() {
349352
// CHECK-NEXT: OSSSharedClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
350353
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{.*}}> 'int [10][10]' lvalue Var 0x{{[^ ]*}} 'array' 'int [10][10]'
351354

355+
// CHECK: OSSTaskDirective 0x{{[^ ]*}} <line:{{[^ ]*}}:{{[^ ]*}}, col:{{[^ ]*}}>
356+
// CHECK-NEXT: OSSDependClause 0x{{[^ ]*}} <col:{{[^ ]*}}, col:{{[^ ]*}}> <oss syntax>
357+
// CHECK-NEXT: OSSArraySectionExpr 0x{{[^ ]*}} <col:{{[^ ]*}}, col:{{[^ ]*}}> '<OmpSs-2 array section type>' lvalue
358+
// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int (*)[10]' <ArrayToPointerDecay>
359+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int [10][10]' lvalue Var 0x{{[^ ]*}} 'array' 'int [10][10]'
360+
// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:{{[^ ]*}}, col:{{[^ ]*}}> 'int' <LValueToRValue>
361+
// CHECK-NEXT: ArraySubscriptExpr 0x{{[^ ]*}} <col:{{[^ ]*}}, col:{{[^ ]*}}> 'int' lvalue
362+
// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int *' <ArrayToPointerDecay>
363+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int [5]' lvalue Var 0x{{[^ ]*}} 'barr' 'int [5]'
364+
// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int' 4
365+
// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:{{[^ ]*}}, col:{{[^ ]*}}> 'int' <LValueToRValue>
366+
// CHECK-NEXT: ArraySubscriptExpr 0x{{[^ ]*}} <col:{{[^ ]*}}, col:{{[^ ]*}}> 'int' lvalue
367+
// CHECK-NEXT: ImplicitCastExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int *' <ArrayToPointerDecay>
368+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int [5]' lvalue Var 0x{{[^ ]*}} 'carr' 'int [5]'
369+
// CHECK-NEXT: IntegerLiteral 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int' 5
370+
// CHECK-NEXT: OSSSharedClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
371+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int [10][10]' lvalue Var 0x{{[^ ]*}} 'array' 'int [10][10]'
372+
// CHECK-NEXT: OSSFirstprivateClause 0x{{[^ ]*}} <<invalid sloc>> <implicit>
373+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int [5]' lvalue Var 0x{{[^ ]*}} 'barr' 'int [5]'
374+
// CHECK-NEXT: DeclRefExpr 0x{{[^ ]*}} <col:{{[^ ]*}}> 'int [5]' lvalue Var 0x{{[^ ]*}} 'carr' 'int [5]'
375+
352376

clang/test/OmpSs/AST/task_depend.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ void bar()
4747
// CHECK: OSSTaskDirective {{[a-z0-9]+}} <line:8:17, col:39>
4848
// CHECK-NEXT: OSSDependClause {{[a-z0-9]+}} <col:26, col:38>
4949
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <col:37> 'int *' lvalue ParmVar {{[a-z0-9]+}} 't' 'int *'
50-
// CHECK-NEXT: OSSFirstprivateClause {{[a-z0-9]+}} <<invalid sloc>> <implicit>
50+
// CHECK-NEXT: OSSSharedClause {{[a-z0-9]+}} <<invalid sloc>> <implicit>
5151
// CHECK-NEXT: DeclRefExpr {{[a-z0-9]+}} <col:37> 'int *' lvalue ParmVar {{[a-z0-9]+}} 't' 'int *'
5252

5353
// CHECK: OSSTaskDirective {{[a-z0-9]+}} <line:19:13, col:38>

clang/test/OmpSs/IR/task_depend1.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ void foo(void) {
1010
}
1111

1212
// CHECK: %arraydecay = getelementptr inbounds [5 x i32], [5 x i32]* %ai, i64 0, i64 0
13-
// CHECK-NEXT: %0 = call token @llvm.directive.region.entry() [ "DIR.OSS"([5 x i8] c"TASK\00"), "QUAL.OSS.SHARED"(i32* %i), "QUAL.OSS.SHARED"([5 x i32]* %ai), "QUAL.OSS.FIRSTPRIVATE"(i32** %pi), "QUAL.OSS.DEP.IN"(i32* %i, i64 4, i64 0, i64 4), "QUAL.OSS.DEP.IN"(i32** %pi, i64 8, i64 0, i64 8), "QUAL.OSS.DEP.IN"(i32* %arraydecay, i64 20, i64 12, i64 16) ]
13+
// CHECK-NEXT: %0 = call token @llvm.directive.region.entry() [ "DIR.OSS"([5 x i8] c"TASK\00"), "QUAL.OSS.SHARED"(i32* %i), "QUAL.OSS.SHARED"(i32** %pi), "QUAL.OSS.SHARED"([5 x i32]* %ai), "QUAL.OSS.DEP.IN"(i32* %i, i64 4, i64 0, i64 4), "QUAL.OSS.DEP.IN"(i32** %pi, i64 8, i64 0, i64 8), "QUAL.OSS.DEP.IN"(i32* %arraydecay, i64 20, i64 12, i64 16) ]
1414
// CHECK-NEXT: %arrayidx = getelementptr inbounds [5 x i32], [5 x i32]* %ai, i64 0, i64 2
1515
// CHECK-NEXT: %1 = load i32, i32* %arrayidx, align 8
1616
// CHECK-NEXT: %2 = load i32*, i32** %pi, align 8

clang/test/OmpSs/IR/task_depend2.c

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ void foo1() {
2424
// CHECK-NEXT: %2 = load i32**, i32*** %a, align 8
2525
// CHECK-NEXT: %arrayidx = getelementptr inbounds i32*, i32** %2, i64 1
2626
// CHECK-NEXT: %3 = load i32*, i32** %arrayidx, align 8
27-
// CHECK-NEXT: %4 = call token @llvm.directive.region.entry() [ "DIR.OSS"([5 x i8] c"TASK\00"), "QUAL.OSS.FIRSTPRIVATE"(i32*** %a), "QUAL.OSS.DEP.IN"(i32*** %a, i64 8, i64 0, i64 8), "QUAL.OSS.DEP.IN"(i32** %0, i64 8, i64 0, i64 8), "QUAL.OSS.DEP.IN"(i32** %1, i64 8, i64 8, i64 16), "QUAL.OSS.DEP.IN"(i32* %3, i64 4, i64 8, i64 12) ]
27+
// CHECK-NEXT: %4 = call token @llvm.directive.region.entry() [ "DIR.OSS"([5 x i8] c"TASK\00"), "QUAL.OSS.SHARED"(i32*** %a), "QUAL.OSS.DEP.IN"(i32*** %a, i64 8, i64 0, i64 8), "QUAL.OSS.DEP.IN"(i32** %0, i64 8, i64 0, i64 8), "QUAL.OSS.DEP.IN"(i32** %1, i64 8, i64 8, i64 16), "QUAL.OSS.DEP.IN"(i32* %3, i64 4, i64 8, i64 12) ]
2828
// CHECK-NEXT: call void @llvm.directive.region.exit(token %4)
2929

3030
// CHECK: %arraydecay = getelementptr inbounds [5 x [6 x i32]], [5 x [6 x i32]]* %b, i64 0, i64 0
@@ -33,6 +33,12 @@ void foo1() {
3333
// CHECK-NEXT: %5 = call token @llvm.directive.region.entry() [ "DIR.OSS"([5 x i8] c"TASK\00"), "QUAL.OSS.SHARED"([5 x [6 x i32]]* %b), "QUAL.OSS.DEP.IN"([5 x [6 x i32]]* %b, i64 24, i64 0, i64 24, i64 5, i64 0, i64 5), "QUAL.OSS.DEP.IN"([6 x i32]* %arraydecay, i64 24, i64 0, i64 24), "QUAL.OSS.DEP.IN"([6 x i32]* %arraydecay1, i64 24, i64 0, i64 24, i64 5, i64 1, i64 2), "QUAL.OSS.DEP.IN"([6 x i32]* %arraydecay2, i64 24, i64 8, i64 12, i64 5, i64 1, i64 2) ]
3434
// CHECK-NEXT: call void @llvm.directive.region.exit(token %5)
3535

36+
// CHECK: %6 = load [5 x i32]*, [5 x i32]** %c, align 8
37+
// CHECK-NEXT: %7 = load [5 x i32]*, [5 x i32]** %c, align 8
38+
// CHECK-NEXT: %8 = load [5 x i32]*, [5 x i32]** %c, align 8
39+
// CHECK-NEXT: %9 = call token @llvm.directive.region.entry() [ "DIR.OSS"([5 x i8] c"TASK\00"), "QUAL.OSS.SHARED"([5 x i32]** %c), "QUAL.OSS.DEP.IN"([5 x i32]** %c, i64 8, i64 0, i64 8), "QUAL.OSS.DEP.IN"([5 x i32]* %6, i64 20, i64 0, i64 20), "QUAL.OSS.DEP.IN"([5 x i32]* %7, i64 20, i64 0, i64 20, i64 1, i64 1, i64 2), "QUAL.OSS.DEP.IN"([5 x i32]* %8, i64 20, i64 8, i64 12, i64 1, i64 1, i64 2) ]
40+
// CHECK-NEXT: call void @llvm.directive.region.exit(token %9)
41+
3642
// CHECK: %arraydecay3 = getelementptr inbounds [5 x [6 x [7 x i32]]], [5 x [6 x [7 x i32]]]* %d, i64 0, i64 0
3743
// CHECK-NEXT: %10 = call token @llvm.directive.region.entry() [ "DIR.OSS"([5 x i8] c"TASK\00"), "QUAL.OSS.SHARED"([5 x [6 x [7 x i32]]]* %d), "QUAL.OSS.DEP.IN"([5 x [6 x [7 x i32]]]* %d, i64 28, i64 0, i64 28, i64 6, i64 0, i64 6, i64 5, i64 0, i64 5), "QUAL.OSS.DEP.IN"([6 x [7 x i32]]* %arraydecay3, i64 28, i64 12, i64 16, i64 6, i64 2, i64 3, i64 5, i64 1, i64 2) ]
3844
// CHECK-NEXT: call void @llvm.directive.region.exit(token %10)

clang/test/OmpSs/Sema/task_depend_dsa_conflict.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,14 +12,14 @@ int main() {
1212

1313
int i;
1414
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}}
15+
#pragma oss task private(i) depend(inout: i)
16+
#pragma oss task depend(inout: i) private(i)
1717
#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}}
18+
#pragma oss task shared(p) depend(inout: p[2])
19+
#pragma oss task shared(p) depend(inout: *p)
2020
#pragma oss task firstprivate(array) depend(inout: array[2]) // expected-error {{the data-sharing 'firstprivate' conflicts with 'shared' required by the dependency}}
2121
#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}}
22+
#pragma oss task shared(ps) depend(inout: ps->x)
2323
{}
2424
}
2525

0 commit comments

Comments
 (0)