Skip to content

Commit a13c514

Browse files
committed
[OpenACC] Implement firstprivate clause for compute constructs
This clause is pretty nearly copy/paste from private, except that it doesn't support 'loop', and thus 'kernelsloop' for appertainment.
1 parent 72e07d4 commit a13c514

17 files changed

+377
-24
lines changed

clang/include/clang/AST/OpenACCClause.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -294,6 +294,25 @@ class OpenACCPrivateClause final
294294
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
295295
};
296296

297+
class OpenACCFirstPrivateClause final
298+
: public OpenACCClauseWithVarList,
299+
public llvm::TrailingObjects<OpenACCFirstPrivateClause, Expr *> {
300+
301+
OpenACCFirstPrivateClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
302+
ArrayRef<Expr *> VarList, SourceLocation EndLoc)
303+
: OpenACCClauseWithVarList(OpenACCClauseKind::FirstPrivate, BeginLoc,
304+
LParenLoc, EndLoc) {
305+
std::uninitialized_copy(VarList.begin(), VarList.end(),
306+
getTrailingObjects<Expr *>());
307+
setExprs(MutableArrayRef(getTrailingObjects<Expr *>(), VarList.size()));
308+
}
309+
310+
public:
311+
static OpenACCFirstPrivateClause *
312+
Create(const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
313+
ArrayRef<Expr *> VarList, SourceLocation EndLoc);
314+
};
315+
297316
template <class Impl> class OpenACCClauseVisitor {
298317
Impl &getDerived() { return static_cast<Impl &>(*this); }
299318

clang/include/clang/Basic/OpenACCClauses.def

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,12 @@
1616
// VISIT_CLAUSE(CLAUSE_NAME)
1717

1818
VISIT_CLAUSE(Default)
19+
VISIT_CLAUSE(FirstPrivate)
1920
VISIT_CLAUSE(If)
20-
VISIT_CLAUSE(Self)
2121
VISIT_CLAUSE(NumGangs)
2222
VISIT_CLAUSE(NumWorkers)
2323
VISIT_CLAUSE(Private)
24+
VISIT_CLAUSE(Self)
2425
VISIT_CLAUSE(VectorLength)
2526

2627
#undef VISIT_CLAUSE

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ class SemaOpenACC : public SemaBase {
117117
}
118118

119119
ArrayRef<Expr *> getVarList() {
120-
assert(ClauseKind == OpenACCClauseKind::Private &&
120+
assert((ClauseKind == OpenACCClauseKind::Private ||
121+
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
121122
"Parsed clause kind does not have a var-list");
122123
return std::get<VarListDetails>(Details).VarList;
123124
}
@@ -165,13 +166,15 @@ class SemaOpenACC : public SemaBase {
165166
}
166167

167168
void setVarListDetails(ArrayRef<Expr *> VarList) {
168-
assert(ClauseKind == OpenACCClauseKind::Private &&
169+
assert((ClauseKind == OpenACCClauseKind::Private ||
170+
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
169171
"Parsed clause kind does not have a var-list");
170172
Details = VarListDetails{{VarList.begin(), VarList.end()}};
171173
}
172174

173175
void setVarListDetails(llvm::SmallVector<Expr *> &&VarList) {
174-
assert(ClauseKind == OpenACCClauseKind::Private &&
176+
assert((ClauseKind == OpenACCClauseKind::Private ||
177+
ClauseKind == OpenACCClauseKind::FirstPrivate) &&
175178
"Parsed clause kind does not have a var-list");
176179
Details = VarListDetails{std::move(VarList)};
177180
}

clang/lib/AST/OpenACCClause.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,15 @@ OpenACCPrivateClause *OpenACCPrivateClause::Create(const ASTContext &C,
144144
return new (Mem) OpenACCPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc);
145145
}
146146

147+
OpenACCFirstPrivateClause *OpenACCFirstPrivateClause::Create(
148+
const ASTContext &C, SourceLocation BeginLoc, SourceLocation LParenLoc,
149+
ArrayRef<Expr *> VarList, SourceLocation EndLoc) {
150+
void *Mem = C.Allocate(
151+
OpenACCFirstPrivateClause::totalSizeToAlloc<Expr *>(VarList.size()));
152+
return new (Mem)
153+
OpenACCFirstPrivateClause(BeginLoc, LParenLoc, VarList, EndLoc);
154+
}
155+
147156
//===----------------------------------------------------------------------===//
148157
// OpenACC clauses printing methods
149158
//===----------------------------------------------------------------------===//
@@ -198,3 +207,11 @@ void OpenACCClausePrinter::VisitPrivateClause(const OpenACCPrivateClause &C) {
198207
[&](const Expr *E) { printExpr(E); });
199208
OS << ")";
200209
}
210+
211+
void OpenACCClausePrinter::VisitFirstPrivateClause(
212+
const OpenACCFirstPrivateClause &C) {
213+
OS << "firstprivate(";
214+
llvm::interleaveComma(C.getVarList(), OS,
215+
[&](const Expr *E) { printExpr(E); });
216+
OS << ")";
217+
}

clang/lib/AST/StmtProfile.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2515,6 +2515,12 @@ void OpenACCClauseProfiler::VisitPrivateClause(
25152515
Profiler.VisitStmt(E);
25162516
}
25172517

2518+
void OpenACCClauseProfiler::VisitFirstPrivateClause(
2519+
const OpenACCFirstPrivateClause &Clause) {
2520+
for (auto *E : Clause.getVarList())
2521+
Profiler.VisitStmt(E);
2522+
}
2523+
25182524
void OpenACCClauseProfiler::VisitVectorLengthClause(
25192525
const OpenACCVectorLengthClause &Clause) {
25202526
assert(Clause.hasIntExpr() &&

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -398,10 +398,11 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
398398
OS << '(' << cast<OpenACCDefaultClause>(C)->getDefaultClauseKind() << ')';
399399
break;
400400
case OpenACCClauseKind::If:
401-
case OpenACCClauseKind::Self:
401+
case OpenACCClauseKind::FirstPrivate:
402402
case OpenACCClauseKind::NumGangs:
403403
case OpenACCClauseKind::NumWorkers:
404404
case OpenACCClauseKind::Private:
405+
case OpenACCClauseKind::Self:
405406
case OpenACCClauseKind::VectorLength:
406407
// The condition expression will be printed as a part of the 'children',
407408
// but print 'clause' here so it is clear what is happening from the dump.

clang/lib/Parse/ParseOpenACC.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -926,14 +926,14 @@ Parser::OpenACCClauseParseResult Parser::ParseOpenACCClauseParams(
926926
case OpenACCClauseKind::Device:
927927
case OpenACCClauseKind::DeviceResident:
928928
case OpenACCClauseKind::DevicePtr:
929-
case OpenACCClauseKind::FirstPrivate:
930929
case OpenACCClauseKind::Host:
931930
case OpenACCClauseKind::Link:
932931
case OpenACCClauseKind::NoCreate:
933932
case OpenACCClauseKind::Present:
934933
case OpenACCClauseKind::UseDevice:
935934
ParseOpenACCVarList();
936935
break;
936+
case OpenACCClauseKind::FirstPrivate:
937937
case OpenACCClauseKind::Private:
938938
ParsedClause.setVarListDetails(ParseOpenACCVarList());
939939
break;

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,16 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
104104
default:
105105
return false;
106106
}
107+
case OpenACCClauseKind::FirstPrivate:
108+
switch (DirectiveKind) {
109+
case OpenACCDirectiveKind::Parallel:
110+
case OpenACCDirectiveKind::Serial:
111+
case OpenACCDirectiveKind::ParallelLoop:
112+
case OpenACCDirectiveKind::SerialLoop:
113+
return true;
114+
default:
115+
return false;
116+
}
107117
case OpenACCClauseKind::Private:
108118
switch (DirectiveKind) {
109119
case OpenACCDirectiveKind::Parallel:
@@ -331,6 +341,21 @@ SemaOpenACC::ActOnClause(ArrayRef<const OpenACCClause *> ExistingClauses,
331341
getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
332342
Clause.getVarList(), Clause.getEndLoc());
333343
}
344+
case OpenACCClauseKind::FirstPrivate: {
345+
// Restrictions only properly implemented on 'compute' constructs, and
346+
// 'compute' constructs are the only construct that can do anything with
347+
// this yet, so skip/treat as unimplemented in this case.
348+
if (!isOpenACCComputeDirectiveKind(Clause.getDirectiveKind()))
349+
break;
350+
351+
// ActOnVar ensured that everything is a valid variable reference, so there
352+
// really isn't anything to do here. GCC does some duplicate-finding, though
353+
// it isn't apparent in the standard where this is justified.
354+
355+
return OpenACCFirstPrivateClause::Create(
356+
getASTContext(), Clause.getBeginLoc(), Clause.getLParenLoc(),
357+
Clause.getVarList(), Clause.getEndLoc());
358+
}
334359
default:
335360
break;
336361
}

clang/lib/Sema/TreeTransform.h

Lines changed: 28 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -11112,6 +11112,23 @@ class OpenACCClauseTransform final
1111211112
SemaOpenACC::OpenACCParsedClause &ParsedClause;
1111311113
OpenACCClause *NewClause = nullptr;
1111411114

11115+
llvm::SmallVector<Expr *> VisitVarList(ArrayRef<Expr *> VarList) {
11116+
llvm::SmallVector<Expr *> InstantiatedVarList;
11117+
for (Expr *CurVar : VarList) {
11118+
ExprResult Res = Self.TransformExpr(CurVar);
11119+
11120+
if (!Res.isUsable())
11121+
continue;
11122+
11123+
Res = Self.getSema().OpenACC().ActOnVar(Res.get());
11124+
11125+
if (Res.isUsable())
11126+
InstantiatedVarList.push_back(Res.get());
11127+
}
11128+
11129+
return InstantiatedVarList;
11130+
}
11131+
1111511132
public:
1111611133
OpenACCClauseTransform(TreeTransform<Derived> &Self,
1111711134
ArrayRef<const OpenACCClause *> ExistingClauses,
@@ -11206,22 +11223,20 @@ void OpenACCClauseTransform<Derived>::VisitNumGangsClause(
1120611223
template <typename Derived>
1120711224
void OpenACCClauseTransform<Derived>::VisitPrivateClause(
1120811225
const OpenACCPrivateClause &C) {
11209-
llvm::SmallVector<Expr *> InstantiatedVarList;
11210-
11211-
for (Expr *CurVar : C.getVarList()) {
11212-
ExprResult Res = Self.TransformExpr(CurVar);
11213-
11214-
if (!Res.isUsable())
11215-
return;
11226+
ParsedClause.setVarListDetails(VisitVarList(C.getVarList()));
1121611227

11217-
Res = Self.getSema().OpenACC().ActOnVar(Res.get());
11228+
NewClause = OpenACCPrivateClause::Create(
11229+
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
11230+
ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
11231+
ParsedClause.getEndLoc());
11232+
}
1121811233

11219-
if (Res.isUsable())
11220-
InstantiatedVarList.push_back(Res.get());
11221-
}
11222-
ParsedClause.setVarListDetails(std::move(InstantiatedVarList));
11234+
template <typename Derived>
11235+
void OpenACCClauseTransform<Derived>::VisitFirstPrivateClause(
11236+
const OpenACCFirstPrivateClause &C) {
11237+
ParsedClause.setVarListDetails(VisitVarList(C.getVarList()));
1122311238

11224-
NewClause = OpenACCPrivateClause::Create(
11239+
NewClause = OpenACCFirstPrivateClause::Create(
1122511240
Self.getSema().getASTContext(), ParsedClause.getBeginLoc(),
1122611241
ParsedClause.getLParenLoc(), ParsedClause.getVarList(),
1122711242
ParsedClause.getEndLoc());

clang/lib/Serialization/ASTReader.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11835,6 +11835,12 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
1183511835
return OpenACCPrivateClause::Create(getContext(), BeginLoc, LParenLoc,
1183611836
VarList, EndLoc);
1183711837
}
11838+
case OpenACCClauseKind::FirstPrivate: {
11839+
SourceLocation LParenLoc = readSourceLocation();
11840+
llvm::SmallVector<Expr *> VarList = readOpenACCVarList();
11841+
return OpenACCFirstPrivateClause::Create(getContext(), BeginLoc, LParenLoc,
11842+
VarList, EndLoc);
11843+
}
1183811844
case OpenACCClauseKind::Finalize:
1183911845
case OpenACCClauseKind::IfPresent:
1184011846
case OpenACCClauseKind::Seq:
@@ -11851,7 +11857,6 @@ OpenACCClause *ASTRecordReader::readOpenACCClause() {
1185111857
case OpenACCClauseKind::Device:
1185211858
case OpenACCClauseKind::DevicePtr:
1185311859
case OpenACCClauseKind::DeviceResident:
11854-
case OpenACCClauseKind::FirstPrivate:
1185511860
case OpenACCClauseKind::Host:
1185611861
case OpenACCClauseKind::Link:
1185711862
case OpenACCClauseKind::NoCreate:

clang/lib/Serialization/ASTWriter.cpp

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7787,6 +7787,12 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
77877787
writeOpenACCVarList(PC);
77887788
return;
77897789
}
7790+
case OpenACCClauseKind::FirstPrivate: {
7791+
const auto *FPC = cast<OpenACCFirstPrivateClause>(C);
7792+
writeSourceLocation(FPC->getLParenLoc());
7793+
writeOpenACCVarList(FPC);
7794+
return;
7795+
}
77907796
case OpenACCClauseKind::Finalize:
77917797
case OpenACCClauseKind::IfPresent:
77927798
case OpenACCClauseKind::Seq:
@@ -7803,7 +7809,6 @@ void ASTRecordWriter::writeOpenACCClause(const OpenACCClause *C) {
78037809
case OpenACCClauseKind::Device:
78047810
case OpenACCClauseKind::DevicePtr:
78057811
case OpenACCClauseKind::DeviceResident:
7806-
case OpenACCClauseKind::FirstPrivate:
78077812
case OpenACCClauseKind::Host:
78087813
case OpenACCClauseKind::Link:
78097814
case OpenACCClauseKind::NoCreate:

clang/test/AST/ast-print-openacc-compute-construct.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,5 +38,9 @@ void foo() {
3838
// CHECK: #pragma acc parallel private(i, array[1], array, array[1:2])
3939
#pragma acc parallel private(i, array[1], array, array[1:2])
4040
while(true);
41+
42+
// CHECK: #pragma acc parallel firstprivate(i, array[1], array, array[1:2])
43+
#pragma acc parallel firstprivate(i, array[1], array, array[1:2])
44+
while(true);
4145
}
4246

clang/test/ParserOpenACC/parse-clauses.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -598,13 +598,11 @@ void VarListClauses() {
598598
#pragma acc serial private(s.array[s.value : 5], s.value), seq
599599
for(;;){}
600600

601-
// expected-error@+3{{expected ','}}
602-
// expected-warning@+2{{OpenACC clause 'firstprivate' not yet implemented, clause ignored}}
601+
// expected-error@+2{{expected ','}}
603602
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
604603
#pragma acc serial firstprivate(s.array[s.value] s.array[s.value :5] ), seq
605604
for(;;){}
606605

607-
// expected-warning@+2{{OpenACC clause 'firstprivate' not yet implemented, clause ignored}}
608606
// expected-warning@+1{{OpenACC clause 'seq' not yet implemented, clause ignored}}
609607
#pragma acc serial firstprivate(s.array[s.value : 5], s.value), seq
610608
for(;;){}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// RUN: %clang_cc1 %s -fopenacc -verify
2+
3+
typedef struct IsComplete {
4+
struct S { int A; } CompositeMember;
5+
int ScalarMember;
6+
float ArrayMember[5];
7+
void *PointerMember;
8+
} Complete;
9+
void uses(int IntParam, short *PointerParam, float ArrayParam[5], Complete CompositeParam) {
10+
int LocalInt;
11+
short *LocalPointer;
12+
float LocalArray[5];
13+
Complete LocalComposite;
14+
// Check Appertainment:
15+
#pragma acc parallel firstprivate(LocalInt)
16+
while(1);
17+
#pragma acc serial firstprivate(LocalInt)
18+
while(1);
19+
// expected-error@+1{{OpenACC 'firstprivate' clause is not valid on 'kernels' directive}}
20+
#pragma acc kernels firstprivate(LocalInt)
21+
while(1);
22+
23+
// Valid cases:
24+
#pragma acc parallel firstprivate(LocalInt, LocalPointer, LocalArray)
25+
while(1);
26+
#pragma acc parallel firstprivate(LocalArray[2:1])
27+
while(1);
28+
29+
#pragma acc parallel firstprivate(LocalComposite.ScalarMember, LocalComposite.ScalarMember)
30+
while(1);
31+
32+
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, or composite variable member}}
33+
#pragma acc parallel firstprivate(1 + IntParam)
34+
while(1);
35+
36+
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, or composite variable member}}
37+
#pragma acc parallel firstprivate(+IntParam)
38+
while(1);
39+
40+
// expected-error@+1{{OpenACC sub-array length is unspecified and cannot be inferred because the subscripted value is not an array}}
41+
#pragma acc parallel firstprivate(PointerParam[2:])
42+
while(1);
43+
44+
// expected-error@+1{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}}
45+
#pragma acc parallel firstprivate(ArrayParam[2:5])
46+
while(1);
47+
48+
// expected-error@+2{{OpenACC sub-array specified range [2:5] would be out of the range of the subscripted array size of 5}}
49+
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, or composite variable member}}
50+
#pragma acc parallel firstprivate((float*)ArrayParam[2:5])
51+
while(1);
52+
// expected-error@+1{{OpenACC variable is not a valid variable name, sub-array, array element, or composite variable member}}
53+
#pragma acc parallel firstprivate((float)ArrayParam[2])
54+
while(1);
55+
}

0 commit comments

Comments
 (0)