Skip to content

Commit a86d00c

Browse files
committed
[OpenACC] Implement combined constr 'seq'/'independent'/'auto' clauses
These three are identical to the version on compute constructs, so this patch implements the tests for it, and ensures that we properly validate it against all the other clauses we're supposed to. The test is mostly a mock-up at the moment, since most other clauses aren't implemented yet for 'loop'.
1 parent 8cc616b commit a86d00c

File tree

6 files changed

+1315
-171
lines changed

6 files changed

+1315
-171
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12689,7 +12689,7 @@ def err_acc_clause_after_device_type
1268912689
"%select{'%3'|compute}2 construct">;
1269012690
def err_acc_clause_cannot_combine
1269112691
: Error<"OpenACC clause '%0' may not appear on the same construct as a "
12692-
"'%1' clause on a 'loop' construct">;
12692+
"'%1' clause on a '%2' construct">;
1269312693
def err_acc_reduction_num_gangs_conflict
1269412694
: Error<
1269512695
"OpenACC 'reduction' clause may not appear on a 'parallel' construct "

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 31 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,26 @@ bool checkValidAfterDeviceType(
479479
default:
480480
break;
481481
}
482+
} else if (isOpenACCCombinedDirectiveKind(NewClause.getDirectiveKind())) {
483+
// This seems like it should be the union of 2.9 and 2.5.4 from above.
484+
switch (NewClause.getClauseKind()) {
485+
case OpenACCClauseKind::Async:
486+
case OpenACCClauseKind::Wait:
487+
case OpenACCClauseKind::NumGangs:
488+
case OpenACCClauseKind::NumWorkers:
489+
case OpenACCClauseKind::VectorLength:
490+
case OpenACCClauseKind::Collapse:
491+
case OpenACCClauseKind::Gang:
492+
case OpenACCClauseKind::Worker:
493+
case OpenACCClauseKind::Vector:
494+
case OpenACCClauseKind::Seq:
495+
case OpenACCClauseKind::Independent:
496+
case OpenACCClauseKind::Auto:
497+
case OpenACCClauseKind::Tile:
498+
return false;
499+
default:
500+
break;
501+
}
482502
}
483503
S.Diag(NewClause.getBeginLoc(), diag::err_acc_clause_after_device_type)
484504
<< NewClause.getClauseKind() << DeviceTypeClause.getClauseKind()
@@ -508,7 +528,8 @@ class SemaOpenACCClauseVisitor {
508528

509529
if (Itr != ExistingClauses.end()) {
510530
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
511-
<< Clause.getClauseKind() << (*Itr)->getClauseKind();
531+
<< Clause.getClauseKind() << (*Itr)->getClauseKind()
532+
<< Clause.getDirectiveKind();
512533
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
513534

514535
return true;
@@ -997,12 +1018,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitDeviceTypeClause(
9971018

9981019
OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
9991020
SemaOpenACC::OpenACCParsedClause &Clause) {
1000-
// Restrictions only properly implemented on 'loop' constructs, and it is
1001-
// the only construct that can do anything with this, so skip/treat as
1002-
// unimplemented for the combined constructs.
1003-
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
1004-
return isNotImplemented();
1005-
10061021
// OpenACC 3.3 2.9:
10071022
// Only one of the seq, independent, and auto clauses may appear.
10081023
const auto *Itr =
@@ -1021,12 +1036,6 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitAutoClause(
10211036

10221037
OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
10231038
SemaOpenACC::OpenACCParsedClause &Clause) {
1024-
// Restrictions only properly implemented on 'loop' constructs, and it is
1025-
// the only construct that can do anything with this, so skip/treat as
1026-
// unimplemented for the combined constructs.
1027-
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
1028-
return isNotImplemented();
1029-
10301039
// OpenACC 3.3 2.9:
10311040
// Only one of the seq, independent, and auto clauses may appear.
10321041
const auto *Itr = llvm::find_if(
@@ -1356,10 +1365,10 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
13561365

13571366
OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
13581367
SemaOpenACC::OpenACCParsedClause &Clause) {
1359-
// Restrictions only properly implemented on 'loop' constructs, and it is
1360-
// the only construct that can do anything with this, so skip/treat as
1361-
// unimplemented for the combined constructs.
1362-
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
1368+
// Restrictions only properly implemented on 'loop' constructs and combined ,
1369+
// and it is the only construct that can do anything with this, so skip/treat
1370+
// as unimplemented for the routine constructs.
1371+
if (Clause.getDirectiveKind() == OpenACCDirectiveKind::Routine)
13631372
return isNotImplemented();
13641373

13651374
// OpenACC 3.3 2.9:
@@ -1383,14 +1392,12 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitSeqClause(
13831392

13841393
if (Itr != ExistingClauses.end()) {
13851394
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_cannot_combine)
1386-
<< Clause.getClauseKind() << (*Itr)->getClauseKind();
1395+
<< Clause.getClauseKind() << (*Itr)->getClauseKind()
1396+
<< Clause.getDirectiveKind();
13871397
SemaRef.Diag((*Itr)->getBeginLoc(), diag::note_acc_previous_clause_here);
13881398
return nullptr;
13891399
}
13901400

1391-
// TODO OpenACC: 2.9 ~ line 2010 specifies that the associated loop has some
1392-
// restrictions when there is a 'seq' clause in place. We probably need to
1393-
// implement that.
13941401
return OpenACCSeqClause::Create(Ctx, Clause.getBeginLoc(),
13951402
Clause.getEndLoc());
13961403
}
@@ -1490,6 +1497,9 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitReductionClause(
14901497

14911498
OpenACCClause *SemaOpenACCClauseVisitor::VisitCollapseClause(
14921499
SemaOpenACC::OpenACCParsedClause &Clause) {
1500+
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()) &&
1501+
Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
1502+
return isNotImplemented();
14931503
// Duplicates here are not really sensible. We could possible permit
14941504
// multiples if they all had the same value, but there isn't really a good
14951505
// reason to do so. Also, this simplifies the suppression of duplicates, in

clang/test/ParserOpenACC/parse-clauses.c

Lines changed: 13 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,21 @@ void func() {
5858
#pragma acc loop seq independent, auto
5959
for(int i = 0; i < 5;++i) {}
6060

61-
// expected-warning@+3{{OpenACC clause 'seq' not yet implemented, clause ignored}}
62-
// expected-warning@+2{{OpenACC clause 'independent' not yet implemented, clause ignored}}
63-
// expected-warning@+1{{OpenACC clause 'auto' not yet implemented, clause ignored}}
61+
// expected-error@+3{{OpenACC clause 'independent' on 'kernels loop' construct conflicts with previous data dependence clause}}
62+
// expected-error@+2{{OpenACC clause 'auto' on 'kernels loop' construct conflicts with previous data dependence clause}}
63+
// expected-note@+1 2{{previous clause is here}}
6464
#pragma acc kernels loop seq independent auto
6565
for(int i = 0; i < 5;++i) {}
6666

67-
// expected-warning@+3{{OpenACC clause 'seq' not yet implemented, clause ignored}}
68-
// expected-warning@+2{{OpenACC clause 'independent' not yet implemented, clause ignored}}
69-
// expected-warning@+1{{OpenACC clause 'auto' not yet implemented, clause ignored}}
67+
// expected-error@+3{{OpenACC clause 'independent' on 'serial loop' construct conflicts with previous data dependence clause}}
68+
// expected-error@+2{{OpenACC clause 'auto' on 'serial loop' construct conflicts with previous data dependence clause}}
69+
// expected-note@+1 2{{previous clause is here}}
7070
#pragma acc serial loop seq, independent auto
7171
for(int i = 0; i < 5;++i) {}
7272

73-
// expected-warning@+3{{OpenACC clause 'seq' not yet implemented, clause ignored}}
74-
// expected-warning@+2{{OpenACC clause 'independent' not yet implemented, clause ignored}}
75-
// expected-warning@+1{{OpenACC clause 'auto' not yet implemented, clause ignored}}
73+
// expected-error@+3{{OpenACC clause 'independent' on 'parallel loop' construct conflicts with previous data dependence clause}}
74+
// expected-error@+2{{OpenACC clause 'auto' on 'parallel loop' construct conflicts with previous data dependence clause}}
75+
// expected-note@+1 2{{previous clause is here}}
7676
#pragma acc parallel loop seq independent, auto
7777
for(int i = 0; i < 5;++i) {}
7878

@@ -270,8 +270,7 @@ void SelfClause() {
270270
#pragma acc serial loop self
271271
for(int i = 0; i < 5;++i) {}
272272

273-
// expected-warning@+2{{OpenACC clause 'self' not yet implemented, clause ignored}}
274-
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
273+
// expected-warning@+1{{OpenACC clause 'self' not yet implemented, clause ignored}}
275274
#pragma acc serial loop self, seq
276275
for(int i = 0; i < 5;++i) {}
277276

@@ -310,19 +309,16 @@ void SelfClause() {
310309
for(int i = 0; i < 5;++i) {}
311310

312311

313-
// expected-error@+2{{expected expression}}
314-
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
312+
// expected-error@+1{{expected expression}}
315313
#pragma acc serial loop self(), seq
316314
for(int i = 0; i < 5;++i) {}
317315

318-
// expected-error@+3{{expected expression}}
319316
// expected-error@+2{{expected expression}}
320-
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
317+
// expected-error@+1{{expected expression}}
321318
#pragma acc serial loop self(,), seq
322319
for(int i = 0; i < 5;++i) {}
323320

324-
// expected-error@+2{{use of undeclared identifier 'invalid_expr'}}
325-
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
321+
// expected-error@+1{{use of undeclared identifier 'invalid_expr'}}
326322
#pragma acc serial loop self(invalid_expr), seq
327323
for(int i = 0; i < 5;++i) {}
328324

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
// RUN: %clang_cc1 %s -fopenacc -ast-dump | FileCheck %s
2+
3+
// Test this with PCH.
4+
// RUN: %clang_cc1 %s -fopenacc -emit-pch -o %t %s
5+
// RUN: %clang_cc1 %s -fopenacc -include-pch %t -ast-dump-all | FileCheck %s
6+
#ifndef PCH_HELPER
7+
#define PCH_HELPER
8+
9+
void NormalUses() {
10+
// CHECK: FunctionDecl{{.*}}NormalUses
11+
// CHECK-NEXT: CompoundStmt
12+
13+
#pragma acc parallel loop auto
14+
for(int i = 0; i < 5; ++i){}
15+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop
16+
// CHECK-NEXT: auto clause
17+
// CHECK-NEXT: ForStmt
18+
// CHECK-NEXT: DeclStmt
19+
// CHECK-NEXT: VarDecl{{.*}} i 'int'
20+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0
21+
// CHECK-NEXT: <<<NULL>>>
22+
// CHECK-NEXT: BinaryOperator{{.*}}'<'
23+
// CHECK-NEXT: ImplicitCastExpr
24+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
25+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5
26+
// CHECK-NEXT: UnaryOperator{{.*}}++
27+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
28+
// CHECK-NEXT: CompoundStmt
29+
30+
#pragma acc serial loop seq
31+
for(;;){}
32+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop
33+
// CHECK-NEXT: seq clause
34+
// CHECK-NEXT: ForStmt
35+
// CHECK-NEXT: <<<NULL>>>
36+
// CHECK-NEXT: <<<NULL>>>
37+
// CHECK-NEXT: <<<NULL>>>
38+
// CHECK-NEXT: <<<NULL>>>
39+
// CHECK-NEXT: CompoundStmt
40+
41+
#pragma acc kernels loop independent
42+
for(int i = 0; i < 5; ++i){}
43+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop
44+
// CHECK-NEXT: independent clause
45+
// CHECK-NEXT: ForStmt
46+
// CHECK-NEXT: DeclStmt
47+
// CHECK-NEXT: VarDecl{{.*}} i 'int'
48+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0
49+
// CHECK-NEXT: <<<NULL>>>
50+
// CHECK-NEXT: BinaryOperator{{.*}}'<'
51+
// CHECK-NEXT: ImplicitCastExpr
52+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
53+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5
54+
// CHECK-NEXT: UnaryOperator{{.*}}++
55+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
56+
// CHECK-NEXT: CompoundStmt
57+
}
58+
59+
template<typename T>
60+
void TemplUses() {
61+
// CHECK: FunctionTemplateDecl{{.*}}TemplUses
62+
// CHECK-NEXT: TemplateTypeParmDecl
63+
// CHECK-NEXT: FunctionDecl{{.*}} TemplUses
64+
// CHECK-NEXT: CompoundStmt
65+
66+
#pragma acc parallel loop auto
67+
for(int i = 0; i < 5; ++i){}
68+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop
69+
// CHECK-NEXT: auto clause
70+
// CHECK-NEXT: ForStmt
71+
// CHECK-NEXT: DeclStmt
72+
// CHECK-NEXT: VarDecl{{.*}} i 'int'
73+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0
74+
// CHECK-NEXT: <<<NULL>>>
75+
// CHECK-NEXT: BinaryOperator{{.*}}'<'
76+
// CHECK-NEXT: ImplicitCastExpr
77+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
78+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5
79+
// CHECK-NEXT: UnaryOperator{{.*}}++
80+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
81+
// CHECK-NEXT: CompoundStmt
82+
83+
#pragma acc serial loop seq
84+
for(;;){}
85+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop
86+
// CHECK-NEXT: seq clause
87+
// CHECK-NEXT: ForStmt
88+
// CHECK-NEXT: <<<NULL>>>
89+
// CHECK-NEXT: <<<NULL>>>
90+
// CHECK-NEXT: <<<NULL>>>
91+
// CHECK-NEXT: <<<NULL>>>
92+
// CHECK-NEXT: CompoundStmt
93+
94+
#pragma acc kernels loop independent
95+
for(int i = 0; i < 5; ++i){}
96+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop
97+
// CHECK-NEXT: independent clause
98+
// CHECK-NEXT: ForStmt
99+
// CHECK-NEXT: DeclStmt
100+
// CHECK-NEXT: VarDecl{{.*}} i 'int'
101+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0
102+
// CHECK-NEXT: <<<NULL>>>
103+
// CHECK-NEXT: BinaryOperator{{.*}}'<'
104+
// CHECK-NEXT: ImplicitCastExpr
105+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
106+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5
107+
// CHECK-NEXT: UnaryOperator{{.*}}++
108+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
109+
// CHECK-NEXT: CompoundStmt
110+
111+
// Instantiations.
112+
// CHECK-NEXT: FunctionDecl{{.*}}TemplUses 'void ()' implicit_instantiation
113+
// CHECK-NEXT: TemplateArgument
114+
// CHECK-NEXT: BuiltinType
115+
// CHECK-NEXT: CompoundStmt
116+
117+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} parallel loop
118+
// CHECK-NEXT: auto clause
119+
// CHECK-NEXT: ForStmt
120+
// CHECK-NEXT: DeclStmt
121+
// CHECK-NEXT: VarDecl{{.*}} i 'int'
122+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0
123+
// CHECK-NEXT: <<<NULL>>>
124+
// CHECK-NEXT: BinaryOperator{{.*}}'<'
125+
// CHECK-NEXT: ImplicitCastExpr
126+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
127+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5
128+
// CHECK-NEXT: UnaryOperator{{.*}}++
129+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
130+
// CHECK-NEXT: CompoundStmt
131+
132+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} serial loop
133+
// CHECK-NEXT: seq clause
134+
// CHECK-NEXT: ForStmt
135+
// CHECK-NEXT: <<<NULL>>>
136+
// CHECK-NEXT: <<<NULL>>>
137+
// CHECK-NEXT: <<<NULL>>>
138+
// CHECK-NEXT: <<<NULL>>>
139+
// CHECK-NEXT: CompoundStmt
140+
141+
// CHECK-NEXT: OpenACCCombinedConstruct{{.*}} kernels loop
142+
// CHECK-NEXT: independent clause
143+
// CHECK-NEXT: ForStmt
144+
// CHECK-NEXT: DeclStmt
145+
// CHECK-NEXT: VarDecl{{.*}} i 'int'
146+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 0
147+
// CHECK-NEXT: <<<NULL>>>
148+
// CHECK-NEXT: BinaryOperator{{.*}}'<'
149+
// CHECK-NEXT: ImplicitCastExpr
150+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
151+
// CHECK-NEXT: IntegerLiteral{{.*}} 'int' 5
152+
// CHECK-NEXT: UnaryOperator{{.*}}++
153+
// CHECK-NEXT: DeclRefExpr{{.*}}'i' 'int'
154+
// CHECK-NEXT: CompoundStmt
155+
}
156+
157+
void Inst() {
158+
TemplUses<int>();
159+
}
160+
#endif // PCH_HELPER

0 commit comments

Comments
 (0)