Skip to content

Commit 504b2a8

Browse files
committed
Implement 'bind' restrictions on routine like we previously did for
gang/worker/vector Discussed separately, this seems like the right way forward.
1 parent 71afd23 commit 504b2a8

File tree

2 files changed

+81
-19
lines changed

2 files changed

+81
-19
lines changed

clang/lib/Sema/SemaOpenACCClause.cpp

Lines changed: 40 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -224,29 +224,23 @@ class SemaOpenACCClauseVisitor {
224224
llvm_unreachable("didn't return from switch above?");
225225
}
226226

227-
// Routine has a pretty complicated set of rules for how device_type and the
228-
// gang, worker, vector, and seq clauses work. So diagnose some of it here.
229-
bool CheckValidRoutineGangWorkerVectorSeqNewClause(
230-
SemaOpenACC::OpenACCParsedClause &Clause) {
227+
// Helper for the 'routine' checks during 'new' clause addition. Precondition
228+
// is that we already know the new clause is one of the prohbiited ones.
229+
template <typename Pred>
230+
bool
231+
CheckValidRoutineNewClauseHelper(Pred HasPredicate,
232+
SemaOpenACC::OpenACCParsedClause &Clause) {
231233
if (Clause.getDirectiveKind() != OpenACCDirectiveKind::Routine)
232234
return false;
233235

234-
if (Clause.getClauseKind() != OpenACCClauseKind::Gang &&
235-
Clause.getClauseKind() != OpenACCClauseKind::Vector &&
236-
Clause.getClauseKind() != OpenACCClauseKind::Worker &&
237-
Clause.getClauseKind() != OpenACCClauseKind::Seq)
238-
return false;
239-
auto ProhibitedPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
240-
OpenACCVectorClause, OpenACCSeqClause>;
241-
242236
auto *FirstDeviceType =
243237
llvm::find_if(ExistingClauses, llvm::IsaPred<OpenACCDeviceTypeClause>);
244238

245239
if (FirstDeviceType == ExistingClauses.end()) {
246240
// If there isn't a device type yet, ANY duplicate is wrong.
247241

248242
auto *ExistingProhibitedClause =
249-
llvm::find_if(ExistingClauses, ProhibitedPred);
243+
llvm::find_if(ExistingClauses, HasPredicate);
250244

251245
if (ExistingProhibitedClause == ExistingClauses.end())
252246
return false;
@@ -265,8 +259,7 @@ class SemaOpenACCClauseVisitor {
265259
// between this and the previous 'device_type'.
266260

267261
auto *BeforeDeviceType =
268-
std::find_if(ExistingClauses.begin(), FirstDeviceType, ProhibitedPred);
269-
262+
std::find_if(ExistingClauses.begin(), FirstDeviceType, HasPredicate);
270263
// If there is one before the device_type (and we know we are after a
271264
// device_type), than this is ill-formed.
272265
if (BeforeDeviceType != FirstDeviceType) {
@@ -294,7 +287,7 @@ class SemaOpenACCClauseVisitor {
294287
auto *LastDeviceType = LastDeviceTypeItr.base() - 1;
295288

296289
auto *ExistingProhibitedSinceLastDevice =
297-
std::find_if(LastDeviceType, ExistingClauses.end(), ProhibitedPred);
290+
std::find_if(LastDeviceType, ExistingClauses.end(), HasPredicate);
298291

299292
// No prohibited ones since the last device-type.
300293
if (ExistingProhibitedSinceLastDevice == ExistingClauses.end())
@@ -311,6 +304,35 @@ class SemaOpenACCClauseVisitor {
311304
return true;
312305
}
313306

307+
// Routine has a pretty complicated set of rules for how device_type and the
308+
// gang, worker, vector, and seq clauses work. So diagnose some of it here.
309+
bool CheckValidRoutineGangWorkerVectorSeqNewClause(
310+
SemaOpenACC::OpenACCParsedClause &Clause) {
311+
312+
if (Clause.getClauseKind() != OpenACCClauseKind::Gang &&
313+
Clause.getClauseKind() != OpenACCClauseKind::Vector &&
314+
Clause.getClauseKind() != OpenACCClauseKind::Worker &&
315+
Clause.getClauseKind() != OpenACCClauseKind::Seq)
316+
return false;
317+
auto ProhibitedPred = llvm::IsaPred<OpenACCGangClause, OpenACCWorkerClause,
318+
OpenACCVectorClause, OpenACCSeqClause>;
319+
320+
return CheckValidRoutineNewClauseHelper(ProhibitedPred, Clause);
321+
}
322+
323+
// Bind should have similar rules on a routine as gang/worker/vector/seq,
324+
// except there is no 'must have 1' rule, so we can get all the checking done
325+
// here.
326+
bool
327+
CheckValidRoutineBindNewClause(SemaOpenACC::OpenACCParsedClause &Clause) {
328+
329+
if (Clause.getClauseKind() != OpenACCClauseKind::Bind)
330+
return false;
331+
332+
auto HasBindPred = llvm::IsaPred<OpenACCBindClause>;
333+
return CheckValidRoutineNewClauseHelper(HasBindPred, Clause);
334+
}
335+
314336
// For 'tile' and 'collapse', only allow 1 per 'device_type'.
315337
template <typename TheClauseTy>
316338
bool DisallowSinceLastDeviceType(SemaOpenACC::OpenACCParsedClause &Clause) {
@@ -352,7 +374,8 @@ class SemaOpenACCClauseVisitor {
352374
Clause.getClauseKind(),
353375
Clause.getBeginLoc(), ExistingClauses))
354376
return nullptr;
355-
if (CheckValidRoutineGangWorkerVectorSeqNewClause(Clause))
377+
if (CheckValidRoutineGangWorkerVectorSeqNewClause(Clause) ||
378+
CheckValidRoutineBindNewClause(Clause))
356379
return nullptr;
357380

358381
switch (Clause.getClauseKind()) {

clang/test/SemaOpenACC/routine-construct-clauses.cpp

Lines changed: 41 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ void Func2();
77
#pragma acc routine(Func) vector nohost
88
#pragma acc routine(Func) nohost seq
99
#pragma acc routine(Func) gang
10-
// expected-error@+2{{OpenACC 'bind' clause cannot appear more than once on a 'routine' directive}}
10+
// expected-error@+2{{OpenACC clause 'bind' may not appear on the same construct as a 'bind' clause on a 'routine' construct}}
1111
// expected-note@+1{{previous clause is here}}
1212
#pragma acc routine(Func) gang bind(a) bind(a)
1313

14-
// expected-error@+2{{OpenACC 'bind' clause cannot appear more than once on a 'routine' directive}}
14+
// expected-error@+2{{OpenACC clause 'bind' may not appear on the same construct as a 'bind' clause on a 'routine' construct}}
1515
// expected-note@+1{{previous clause is here}}
1616
#pragma acc routine gang bind(a) bind(a)
1717
void DupeImplName();
@@ -733,3 +733,42 @@ namespace FigureDupesAllowedAroundDeviceType {
733733
void Func113();
734734

735735
}
736+
737+
namespace BindDupes {
738+
// expected-error@+2{{OpenACC clause 'bind' may not appear on the same construct as a 'bind' clause on a 'routine' construct}}
739+
// expected-note@+1{{previous clause is here}}
740+
#pragma acc routine seq bind(asdf) bind(asdf)
741+
void Func1();
742+
// expected-error@+2{{OpenACC clause 'bind' may not appear on the same construct as a 'bind' clause on a 'routine' construct}}
743+
// expected-note@+1{{previous clause is here}}
744+
#pragma acc routine seq bind(asdf) bind(asdf) device_type(*)
745+
void Func2();
746+
// expected-error@+3{{OpenACC clause 'bind' after 'device_type' clause on a 'routine' conflicts with the 'bind' clause before the first 'device_type'}}
747+
// expected-note@+2{{previous clause is here}}
748+
// expected-note@+1{{previous clause is here}}
749+
#pragma acc routine seq bind(asdf) device_type(*) bind(asdf)
750+
void Func3();
751+
// expected-error@+3{{OpenACC clause 'bind' after 'device_type' clause on a 'routine' conflicts with the 'bind' clause before the first 'device_type'}}
752+
// expected-note@+2{{previous clause is here}}
753+
// expected-note@+1{{previous clause is here}}
754+
#pragma acc routine seq bind(asdf) device_type(*) bind(asdf) device_type(*)
755+
void Func4();
756+
// expected-error@+3{{OpenACC clause 'bind' on a 'routine' directive conflicts with the 'bind' clause applying to the same 'device_type'}}
757+
// expected-note@+2{{previous clause is here}}
758+
// expected-note@+1{{previous clause is here}}
759+
#pragma acc routine seq device_type(*) bind(asdf) bind(asdf)
760+
void Func5();
761+
// expected-error@+3{{OpenACC clause 'bind' on a 'routine' directive conflicts with the 'bind' clause applying to the same 'device_type'}}
762+
// expected-note@+2{{previous clause is here}}
763+
// expected-note@+1{{previous clause is here}}
764+
#pragma acc routine seq device_type(*) bind(asdf) bind(asdf) device_type(*)
765+
void Func6();
766+
// expected-error@+3{{OpenACC clause 'bind' on a 'routine' directive conflicts with the 'bind' clause applying to the same 'device_type'}}
767+
// expected-note@+2{{previous clause is here}}
768+
// expected-note@+1{{previous clause is here}}
769+
#pragma acc routine seq device_type(*) bind(asdf) device_type(*) bind(asdf) bind(asdf)
770+
void Func7();
771+
772+
#pragma acc routine seq device_type(*) bind(asdf) device_type(*) bind(asdf)
773+
void Func8();
774+
}

0 commit comments

Comments
 (0)