Skip to content

Commit ccd6cde

Browse files
erichkeaneDanielCChen
authored andcommitted
[OpenACC] Implement 'loop' 'vector' clause (llvm#112259)
The 'vector' clause specifies the iterations to be executed in vector or SIMD mode. There are some limitations on which associated compute contexts may be associated with this and have arguments, but otherwise this is a fairly unrestricted clause. It DOES have region limits like 'gang' and 'worker'.
1 parent f2aacb1 commit ccd6cde

18 files changed

+806
-62
lines changed

clang/include/clang/AST/OpenACCClause.h

Lines changed: 16 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -119,32 +119,6 @@ class OpenACCSeqClause : public OpenACCClause {
119119
}
120120
};
121121

122-
// Not yet implemented, but the type name is necessary for 'seq' diagnostics, so
123-
// this provides a basic, do-nothing implementation. We still need to add this
124-
// type to the visitors/etc, as well as get it to take its proper arguments.
125-
class OpenACCVectorClause : public OpenACCClause {
126-
protected:
127-
OpenACCVectorClause(SourceLocation BeginLoc, SourceLocation EndLoc)
128-
: OpenACCClause(OpenACCClauseKind::Vector, BeginLoc, EndLoc) {
129-
llvm_unreachable("Not yet implemented");
130-
}
131-
132-
public:
133-
static bool classof(const OpenACCClause *C) {
134-
return C->getClauseKind() == OpenACCClauseKind::Vector;
135-
}
136-
137-
static OpenACCVectorClause *
138-
Create(const ASTContext &Ctx, SourceLocation BeginLoc, SourceLocation EndLoc);
139-
140-
child_range children() {
141-
return child_range(child_iterator(), child_iterator());
142-
}
143-
const_child_range children() const {
144-
return const_child_range(const_child_iterator(), const_child_iterator());
145-
}
146-
};
147-
148122
/// Represents a clause that has a list of parameters.
149123
class OpenACCClauseWithParams : public OpenACCClause {
150124
/// Location of the '('.
@@ -531,6 +505,22 @@ class OpenACCWorkerClause : public OpenACCClauseWithSingleIntExpr {
531505
SourceLocation EndLoc);
532506
};
533507

508+
class OpenACCVectorClause : public OpenACCClauseWithSingleIntExpr {
509+
protected:
510+
OpenACCVectorClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
511+
Expr *IntExpr, SourceLocation EndLoc);
512+
513+
public:
514+
static bool classof(const OpenACCClause *C) {
515+
return C->getClauseKind() == OpenACCClauseKind::Vector;
516+
}
517+
518+
static OpenACCVectorClause *Create(const ASTContext &Ctx,
519+
SourceLocation BeginLoc,
520+
SourceLocation LParenLoc, Expr *IntExpr,
521+
SourceLocation EndLoc);
522+
};
523+
534524
class OpenACCNumWorkersClause : public OpenACCClauseWithSingleIntExpr {
535525
OpenACCNumWorkersClause(SourceLocation BeginLoc, SourceLocation LParenLoc,
536526
Expr *IntExpr, SourceLocation EndLoc);

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12702,7 +12702,7 @@ def err_acc_gang_dim_value
1270212702
def err_acc_num_arg_conflict
1270312703
: Error<"'num' argument to '%0' clause not allowed on a 'loop' construct "
1270412704
"associated with a 'kernels' construct that has a "
12705-
"'%select{num_gangs|num_workers}1' "
12705+
"'%select{num_gangs|num_workers|vector_length}1' "
1270612706
"clause">;
1270712707
def err_acc_clause_in_clause_region
1270812708
: Error<"loop with a '%0' clause may not exist in the region of a '%1' "

clang/include/clang/Basic/OpenACCClauses.def

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ VISIT_CLAUSE(Reduction)
5454
VISIT_CLAUSE(Self)
5555
VISIT_CLAUSE(Seq)
5656
VISIT_CLAUSE(Tile)
57+
VISIT_CLAUSE(Vector)
5758
VISIT_CLAUSE(VectorLength)
5859
VISIT_CLAUSE(Wait)
5960
VISIT_CLAUSE(Worker)

clang/include/clang/Sema/SemaOpenACC.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ class SemaOpenACC : public SemaBase {
123123
/// permits us to implement the restriction of no further 'gang' or 'worker'
124124
/// clauses.
125125
SourceLocation LoopWorkerClauseLoc;
126+
/// If there is a current 'active' loop construct with a 'vector' clause on it
127+
/// (on any sort of construct), this has the source location for it. This
128+
/// permits us to implement the restriction of no further 'gang', 'vector', or
129+
/// 'worker' clauses.
130+
SourceLocation LoopVectorClauseLoc;
126131

127132
// Redeclaration of the version in OpenACCClause.h.
128133
using DeviceTypeArgument = std::pair<IdentifierInfo *, SourceLocation>;
@@ -679,6 +684,7 @@ class SemaOpenACC : public SemaBase {
679684
OpenACCDirectiveKind DirKind;
680685
SourceLocation OldLoopGangClauseOnKernelLoc;
681686
SourceLocation OldLoopWorkerClauseLoc;
687+
SourceLocation OldLoopVectorClauseLoc;
682688
llvm::SmallVector<OpenACCLoopConstruct *> ParentlessLoopConstructs;
683689
LoopInConstructRAII LoopRAII;
684690

clang/lib/AST/OpenACCClause.cpp

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,8 +44,8 @@ bool OpenACCClauseWithCondition::classof(const OpenACCClause *C) {
4444
bool OpenACCClauseWithSingleIntExpr::classof(const OpenACCClause *C) {
4545
return OpenACCNumWorkersClause::classof(C) ||
4646
OpenACCVectorLengthClause::classof(C) ||
47-
OpenACCWorkerClause::classof(C) || OpenACCCollapseClause::classof(C) ||
48-
OpenACCAsyncClause::classof(C);
47+
OpenACCVectorClause::classof(C) || OpenACCWorkerClause::classof(C) ||
48+
OpenACCCollapseClause::classof(C) || OpenACCAsyncClause::classof(C);
4949
}
5050
OpenACCDefaultClause *OpenACCDefaultClause::Create(const ASTContext &C,
5151
OpenACCDefaultClauseKind K,
@@ -424,11 +424,24 @@ OpenACCWorkerClause *OpenACCWorkerClause::Create(const ASTContext &C,
424424
return new (Mem) OpenACCWorkerClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
425425
}
426426

427+
OpenACCVectorClause::OpenACCVectorClause(SourceLocation BeginLoc,
428+
SourceLocation LParenLoc,
429+
Expr *IntExpr, SourceLocation EndLoc)
430+
: OpenACCClauseWithSingleIntExpr(OpenACCClauseKind::Vector, BeginLoc,
431+
LParenLoc, IntExpr, EndLoc) {
432+
assert((!IntExpr || IntExpr->isInstantiationDependent() ||
433+
IntExpr->getType()->isIntegerType()) &&
434+
"Int expression type not scalar/dependent");
435+
}
436+
427437
OpenACCVectorClause *OpenACCVectorClause::Create(const ASTContext &C,
428438
SourceLocation BeginLoc,
439+
SourceLocation LParenLoc,
440+
Expr *IntExpr,
429441
SourceLocation EndLoc) {
430-
void *Mem = C.Allocate(sizeof(OpenACCVectorClause));
431-
return new (Mem) OpenACCVectorClause(BeginLoc, EndLoc);
442+
void *Mem =
443+
C.Allocate(sizeof(OpenACCVectorClause), alignof(OpenACCVectorClause));
444+
return new (Mem) OpenACCVectorClause(BeginLoc, LParenLoc, IntExpr, EndLoc);
432445
}
433446

434447
//===----------------------------------------------------------------------===//
@@ -662,3 +675,13 @@ void OpenACCClausePrinter::VisitWorkerClause(const OpenACCWorkerClause &C) {
662675
OS << ")";
663676
}
664677
}
678+
679+
void OpenACCClausePrinter::VisitVectorClause(const OpenACCVectorClause &C) {
680+
OS << "vector";
681+
682+
if (C.hasIntExpr()) {
683+
OS << "(length: ";
684+
printExpr(C.getIntExpr());
685+
OS << ")";
686+
}
687+
}

clang/lib/AST/StmtProfile.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2635,6 +2635,12 @@ void OpenACCClauseProfiler::VisitWorkerClause(
26352635
Profiler.VisitStmt(Clause.getIntExpr());
26362636
}
26372637

2638+
void OpenACCClauseProfiler::VisitVectorClause(
2639+
const OpenACCVectorClause &Clause) {
2640+
if (Clause.hasIntExpr())
2641+
Profiler.VisitStmt(Clause.getIntExpr());
2642+
}
2643+
26382644
void OpenACCClauseProfiler::VisitWaitClause(const OpenACCWaitClause &Clause) {
26392645
if (Clause.hasDevNumExpr())
26402646
Profiler.VisitStmt(Clause.getDevNumExpr());

clang/lib/AST/TextNodeDumper.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ void TextNodeDumper::Visit(const OpenACCClause *C) {
421421
case OpenACCClauseKind::Seq:
422422
case OpenACCClauseKind::Tile:
423423
case OpenACCClauseKind::Worker:
424+
case OpenACCClauseKind::Vector:
424425
case OpenACCClauseKind::VectorLength:
425426
// The condition expression will be printed as a part of the 'children',
426427
// but print 'clause' here so it is clear what is happening from the dump.

clang/lib/Sema/SemaOpenACC.cpp

Lines changed: 138 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,18 @@ bool doesClauseApplyToDirective(OpenACCDirectiveKind DirectiveKind,
389389
return false;
390390
}
391391
}
392+
case OpenACCClauseKind::Vector: {
393+
switch (DirectiveKind) {
394+
case OpenACCDirectiveKind::Loop:
395+
case OpenACCDirectiveKind::ParallelLoop:
396+
case OpenACCDirectiveKind::SerialLoop:
397+
case OpenACCDirectiveKind::KernelsLoop:
398+
case OpenACCDirectiveKind::Routine:
399+
return true;
400+
default:
401+
return false;
402+
}
403+
}
392404
}
393405

394406
default:
@@ -512,14 +524,6 @@ class SemaOpenACCClauseVisitor {
512524

513525
OpenACCClause *Visit(SemaOpenACC::OpenACCParsedClause &Clause) {
514526
switch (Clause.getClauseKind()) {
515-
case OpenACCClauseKind::Vector: {
516-
// TODO OpenACC: These are only implemented enough for the 'seq'
517-
// diagnostic, otherwise treats itself as unimplemented. When we
518-
// implement these, we can remove them from here.
519-
DiagIfSeqClause(Clause);
520-
return isNotImplemented();
521-
}
522-
523527
#define VISIT_CLAUSE(CLAUSE_NAME) \
524528
case OpenACCClauseKind::CLAUSE_NAME: \
525529
return Visit##CLAUSE_NAME##Clause(Clause);
@@ -1035,6 +1039,97 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitIndependentClause(
10351039
Clause.getEndLoc());
10361040
}
10371041

1042+
OpenACCClause *SemaOpenACCClauseVisitor::VisitVectorClause(
1043+
SemaOpenACC::OpenACCParsedClause &Clause) {
1044+
if (DiagIfSeqClause(Clause))
1045+
return nullptr;
1046+
// Restrictions only properly implemented on 'loop' constructs, and it is
1047+
// the only construct that can do anything with this, so skip/treat as
1048+
// unimplemented for the combined constructs.
1049+
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Loop)
1050+
return isNotImplemented();
1051+
1052+
Expr *IntExpr =
1053+
Clause.getNumIntExprs() != 0 ? Clause.getIntExprs()[0] : nullptr;
1054+
if (IntExpr) {
1055+
switch (SemaRef.getActiveComputeConstructInfo().Kind) {
1056+
case OpenACCDirectiveKind::Invalid:
1057+
case OpenACCDirectiveKind::Parallel:
1058+
// No restriction on when 'parallel' can contain an argument.
1059+
break;
1060+
case OpenACCDirectiveKind::Serial:
1061+
// GCC disallows this, and there is no real good reason for us to permit
1062+
// it, so disallow until we come up with a use case that makes sense.
1063+
SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_int_arg_invalid)
1064+
<< OpenACCClauseKind::Vector << "num" << /*serial=*/3;
1065+
IntExpr = nullptr;
1066+
break;
1067+
case OpenACCDirectiveKind::Kernels: {
1068+
const auto *Itr =
1069+
llvm::find_if(SemaRef.getActiveComputeConstructInfo().Clauses,
1070+
llvm::IsaPred<OpenACCVectorLengthClause>);
1071+
if (Itr != SemaRef.getActiveComputeConstructInfo().Clauses.end()) {
1072+
SemaRef.Diag(IntExpr->getBeginLoc(), diag::err_acc_num_arg_conflict)
1073+
<< OpenACCClauseKind::Vector << /*vector_length=*/2;
1074+
SemaRef.Diag((*Itr)->getBeginLoc(),
1075+
diag::note_acc_previous_clause_here);
1076+
1077+
IntExpr = nullptr;
1078+
}
1079+
break;
1080+
}
1081+
default:
1082+
llvm_unreachable("Non compute construct in active compute construct");
1083+
}
1084+
}
1085+
1086+
// OpenACC 3.3 2.9.2: When the parent compute construct is a kernels
1087+
// construct, the gang clause behaves as follows. ... The region of a loop
1088+
// with a gang clause may not contain another loop with a gang clause unless
1089+
// within a nested compute region.
1090+
if (SemaRef.LoopGangClauseOnKernelLoc.isValid()) {
1091+
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
1092+
// one of these until we get to the end of the construct.
1093+
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1094+
<< OpenACCClauseKind::Vector << OpenACCClauseKind::Gang
1095+
<< /*skip kernels construct info*/ 0;
1096+
SemaRef.Diag(SemaRef.LoopGangClauseOnKernelLoc,
1097+
diag::note_acc_previous_clause_here);
1098+
return nullptr;
1099+
}
1100+
1101+
// OpenACC 3.3 2.9.3: The region of a loop with a 'worker' clause may not
1102+
// contain a loop with a gang or worker clause unless within a nested compute
1103+
// region.
1104+
if (SemaRef.LoopWorkerClauseLoc.isValid()) {
1105+
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
1106+
// one of these until we get to the end of the construct.
1107+
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1108+
<< OpenACCClauseKind::Vector << OpenACCClauseKind::Worker
1109+
<< /*skip kernels construct info*/ 0;
1110+
SemaRef.Diag(SemaRef.LoopWorkerClauseLoc,
1111+
diag::note_acc_previous_clause_here);
1112+
return nullptr;
1113+
}
1114+
// OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1115+
// contain a loop with a gang, worker, or vector clause unless within a nested
1116+
// compute region.
1117+
if (SemaRef.LoopVectorClauseLoc.isValid()) {
1118+
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
1119+
// one of these until we get to the end of the construct.
1120+
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1121+
<< OpenACCClauseKind::Vector << OpenACCClauseKind::Vector
1122+
<< /*skip kernels construct info*/ 0;
1123+
SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1124+
diag::note_acc_previous_clause_here);
1125+
return nullptr;
1126+
}
1127+
1128+
return OpenACCVectorClause::Create(Ctx, Clause.getBeginLoc(),
1129+
Clause.getLParenLoc(), IntExpr,
1130+
Clause.getEndLoc());
1131+
}
1132+
10381133
OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
10391134
SemaOpenACC::OpenACCParsedClause &Clause) {
10401135
if (DiagIfSeqClause(Clause))
@@ -1099,6 +1194,20 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitWorkerClause(
10991194
return nullptr;
11001195
}
11011196

1197+
// OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1198+
// contain a loop with a gang, worker, or vector clause unless within a nested
1199+
// compute region.
1200+
if (SemaRef.LoopVectorClauseLoc.isValid()) {
1201+
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
1202+
// one of these until we get to the end of the construct.
1203+
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1204+
<< OpenACCClauseKind::Worker << OpenACCClauseKind::Vector
1205+
<< /*skip kernels construct info*/ 0;
1206+
SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1207+
diag::note_acc_previous_clause_here);
1208+
return nullptr;
1209+
}
1210+
11021211
return OpenACCWorkerClause::Create(Ctx, Clause.getBeginLoc(),
11031212
Clause.getLParenLoc(), IntExpr,
11041213
Clause.getEndLoc());
@@ -1193,6 +1302,20 @@ OpenACCClause *SemaOpenACCClauseVisitor::VisitGangClause(
11931302
return nullptr;
11941303
}
11951304

1305+
// OpenACC 3.3 2.9.4: The region of a loop with a 'vector' clause may not
1306+
// contain a loop with a gang, worker, or vector clause unless within a nested
1307+
// compute region.
1308+
if (SemaRef.LoopVectorClauseLoc.isValid()) {
1309+
// This handles the 'inner loop' diagnostic, but we cannot set that we're on
1310+
// one of these until we get to the end of the construct.
1311+
SemaRef.Diag(Clause.getBeginLoc(), diag::err_acc_clause_in_clause_region)
1312+
<< OpenACCClauseKind::Gang << OpenACCClauseKind::Vector
1313+
<< /*kernels construct info*/ 1;
1314+
SemaRef.Diag(SemaRef.LoopVectorClauseLoc,
1315+
diag::note_acc_previous_clause_here);
1316+
return nullptr;
1317+
}
1318+
11961319
return OpenACCGangClause::Create(Ctx, Clause.getBeginLoc(),
11971320
Clause.getLParenLoc(), GangKinds, IntExprs,
11981321
Clause.getEndLoc());
@@ -1313,6 +1436,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
13131436
: SemaRef(S), OldActiveComputeConstructInfo(S.ActiveComputeConstructInfo),
13141437
DirKind(DK), OldLoopGangClauseOnKernelLoc(S.LoopGangClauseOnKernelLoc),
13151438
OldLoopWorkerClauseLoc(S.LoopWorkerClauseLoc),
1439+
OldLoopVectorClauseLoc(S.LoopVectorClauseLoc),
13161440
LoopRAII(SemaRef, /*PreserveDepth=*/false) {
13171441
// Compute constructs end up taking their 'loop'.
13181442
if (DirKind == OpenACCDirectiveKind::Parallel ||
@@ -1330,6 +1454,7 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
13301454
// Implement the 'unless within a nested compute region' part.
13311455
SemaRef.LoopGangClauseOnKernelLoc = {};
13321456
SemaRef.LoopWorkerClauseLoc = {};
1457+
SemaRef.LoopVectorClauseLoc = {};
13331458
} else if (DirKind == OpenACCDirectiveKind::Loop) {
13341459
SetCollapseInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
13351460
SetTileInfoBeforeAssociatedStmt(UnInstClauses, Clauses);
@@ -1355,6 +1480,10 @@ SemaOpenACC::AssociatedStmtRAII::AssociatedStmtRAII(
13551480
auto *Itr = llvm::find_if(Clauses, llvm::IsaPred<OpenACCWorkerClause>);
13561481
if (Itr != Clauses.end())
13571482
SemaRef.LoopWorkerClauseLoc = (*Itr)->getBeginLoc();
1483+
1484+
auto *Itr2 = llvm::find_if(Clauses, llvm::IsaPred<OpenACCVectorClause>);
1485+
if (Itr2 != Clauses.end())
1486+
SemaRef.LoopVectorClauseLoc = (*Itr2)->getBeginLoc();
13581487
}
13591488
}
13601489
}
@@ -1429,6 +1558,7 @@ SemaOpenACC::AssociatedStmtRAII::~AssociatedStmtRAII() {
14291558
SemaRef.ActiveComputeConstructInfo = OldActiveComputeConstructInfo;
14301559
SemaRef.LoopGangClauseOnKernelLoc = OldLoopGangClauseOnKernelLoc;
14311560
SemaRef.LoopWorkerClauseLoc = OldLoopWorkerClauseLoc;
1561+
SemaRef.LoopVectorClauseLoc = OldLoopVectorClauseLoc;
14321562

14331563
if (DirKind == OpenACCDirectiveKind::Parallel ||
14341564
DirKind == OpenACCDirectiveKind::Serial ||

0 commit comments

Comments
 (0)