Skip to content

Commit e777e7a

Browse files
authored
[OpenACC] Implement better dupe catching for device_type clauses (#138196)
Previously we just checked duplicates for a handful of clauses between active device_type clauses. However, after looking into the implementation for 'collapse', I discovered that duplicate device_type identifiers with duplicate versions of htese clause are problematic. This patch corrects this and now catches these conflicts.
1 parent 32ca368 commit e777e7a

7 files changed

+193
-12
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13000,6 +13000,13 @@ def err_acc_duplicate_clause_disallowed
1300013000
: Error<"OpenACC '%1' clause cannot appear more than once on a '%0' "
1300113001
"directive">;
1300213002
def note_acc_previous_clause_here : Note<"previous clause is here">;
13003+
// TODO(OpenACC): Combine these with the one above, and decide between a
13004+
// 'select' to split between showing the clause name, or just always printing
13005+
// the name.
13006+
def note_acc_previous_named_clause_here : Note<"previous '%0' clause is here">;
13007+
def note_acc_device_type_here
13008+
: Note<"%enum_select<ACCDeviceTypeApp>{%Active{active}|%Applies{which "
13009+
"applies to}}0 'device_type' clause here">;
1300313010
def note_acc_previous_expr_here : Note<"previous expression is here">;
1300413011
def note_acc_previous_reference : Note<"previous reference is here">;
1300513012
def err_acc_branch_in_out_compute_construct
@@ -13085,6 +13092,9 @@ def err_acc_clause_routine_one_of_in_region
1308513092
def err_acc_clause_since_last_device_type
1308613093
: Error<"OpenACC '%0' clause cannot appear more than once%select{| in a "
1308713094
"'device_type' region}2 on a '%1' directive">;
13095+
def err_acc_clause_conflicts_prev_dev_type
13096+
: Error<"OpenACC '%0' clause applies to 'device_type' '%1', which "
13097+
"conflicts with previous '%0' clause">;
1308813098

1308913099
def err_acc_reduction_num_gangs_conflict
1309013100
: Error<"OpenACC '%1' clause %select{|with more than 1 argument }0may not "

clang/lib/Sema/SemaOpenACCClause.cpp

Lines changed: 89 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -335,29 +335,106 @@ class SemaOpenACCClauseVisitor {
335335

336336
// For 'tile' and 'collapse', only allow 1 per 'device_type'.
337337
// Also applies to num_worker, num_gangs, vector_length, and async.
338+
// This does introspection into the actual device-types to prevent duplicates
339+
// across device types as well.
338340
template <typename TheClauseTy>
339341
bool DisallowSinceLastDeviceType(SemaOpenACC::OpenACCParsedClause &Clause) {
340342
auto LastDeviceTypeItr =
341343
std::find_if(ExistingClauses.rbegin(), ExistingClauses.rend(),
342344
llvm::IsaPred<OpenACCDeviceTypeClause>);
343345

344-
auto Last = std::find_if(ExistingClauses.rbegin(), LastDeviceTypeItr,
345-
llvm::IsaPred<TheClauseTy>);
346+
auto LastSinceDevTy =
347+
std::find_if(ExistingClauses.rbegin(), LastDeviceTypeItr,
348+
llvm::IsaPred<TheClauseTy>);
346349

347-
if (Last == LastDeviceTypeItr)
350+
// In this case there is a duplicate since the last device_type/lack of a
351+
// device_type. Diagnose these as duplicates.
352+
if (LastSinceDevTy != LastDeviceTypeItr) {
353+
SemaRef.Diag(Clause.getBeginLoc(),
354+
diag::err_acc_clause_since_last_device_type)
355+
<< Clause.getClauseKind() << Clause.getDirectiveKind()
356+
<< (LastDeviceTypeItr != ExistingClauses.rend());
357+
SemaRef.Diag((*LastSinceDevTy)->getBeginLoc(),
358+
diag::note_acc_previous_clause_here);
359+
360+
// Mention the last device_type as well.
361+
if (LastDeviceTypeItr != ExistingClauses.rend())
362+
SemaRef.Diag((*LastDeviceTypeItr)->getBeginLoc(),
363+
diag::note_acc_previous_clause_here);
364+
return true;
365+
}
366+
367+
// If this isn't in a device_type, and we didn't diagnose that there are
368+
// dupes above, just give up, no sense in searching for previous device_type
369+
// regions as they don't exist.
370+
if (LastDeviceTypeItr == ExistingClauses.rend())
348371
return false;
349372

350-
SemaRef.Diag(Clause.getBeginLoc(),
351-
diag::err_acc_clause_since_last_device_type)
352-
<< Clause.getClauseKind() << Clause.getDirectiveKind()
353-
<< (LastDeviceTypeItr != ExistingClauses.rend());
354-
SemaRef.Diag((*Last)->getBeginLoc(), diag::note_acc_previous_clause_here);
373+
// The device-type that is active for us, so we can compare to the previous
374+
// ones.
375+
const auto &ActiveDeviceTypeClause =
376+
cast<OpenACCDeviceTypeClause>(**LastDeviceTypeItr);
355377

356-
if (LastDeviceTypeItr != ExistingClauses.rend())
357-
SemaRef.Diag((*LastDeviceTypeItr)->getBeginLoc(),
358-
diag::note_acc_previous_clause_here);
378+
auto PrevDeviceTypeItr = LastDeviceTypeItr;
379+
auto CurDevTypeItr = LastDeviceTypeItr;
359380

360-
return true;
381+
while ((CurDevTypeItr = std::find_if(
382+
std::next(PrevDeviceTypeItr), ExistingClauses.rend(),
383+
llvm::IsaPred<OpenACCDeviceTypeClause>)) !=
384+
ExistingClauses.rend()) {
385+
// At this point, we know that we have a region between two device_types,
386+
// as specified by CurDevTypeItr and PrevDeviceTypeItr.
387+
388+
auto CurClauseKindItr = std::find_if(PrevDeviceTypeItr, CurDevTypeItr,
389+
llvm::IsaPred<TheClauseTy>);
390+
391+
// There are no clauses of the current kind between these device_types, so
392+
// continue.
393+
if (CurClauseKindItr == CurDevTypeItr)
394+
continue;
395+
396+
// At this point, we know that this device_type region has a collapse. So
397+
// diagnose if the two device_types have any overlap in their
398+
// architectures.
399+
const auto &CurDeviceTypeClause =
400+
cast<OpenACCDeviceTypeClause>(**CurDevTypeItr);
401+
402+
for (const DeviceTypeArgument &arg :
403+
ActiveDeviceTypeClause.getArchitectures()) {
404+
for (const DeviceTypeArgument &prevArg :
405+
CurDeviceTypeClause.getArchitectures()) {
406+
407+
// This should catch duplicates * regions, duplicate same-text (thanks
408+
// to identifier equiv.) and case insensitive dupes.
409+
if (arg.getIdentifierInfo() == prevArg.getIdentifierInfo() ||
410+
(arg.getIdentifierInfo() && prevArg.getIdentifierInfo() &&
411+
StringRef{arg.getIdentifierInfo()->getName()}.equals_insensitive(
412+
prevArg.getIdentifierInfo()->getName()))) {
413+
SemaRef.Diag(Clause.getBeginLoc(),
414+
diag::err_acc_clause_conflicts_prev_dev_type)
415+
<< Clause.getClauseKind()
416+
<< (arg.getIdentifierInfo() ? arg.getIdentifierInfo()->getName()
417+
: "*");
418+
// mention the active device type.
419+
SemaRef.Diag(ActiveDeviceTypeClause.getBeginLoc(),
420+
diag::note_acc_device_type_here)
421+
<< diag::ACCDeviceTypeApp::Active;
422+
// mention the previous clause.
423+
SemaRef.Diag((*CurClauseKindItr)->getBeginLoc(),
424+
diag::note_acc_previous_named_clause_here)
425+
<< (*CurClauseKindItr)->getClauseKind();
426+
// mention the previous device type.
427+
SemaRef.Diag(CurDeviceTypeClause.getBeginLoc(),
428+
diag::note_acc_device_type_here)
429+
<< diag::ACCDeviceTypeApp::Applies;
430+
return true;
431+
}
432+
}
433+
}
434+
435+
PrevDeviceTypeItr = CurDevTypeItr;
436+
}
437+
return false;
361438
}
362439

363440
public:

clang/test/SemaOpenACC/compute-construct-num_gangs-clause.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,18 @@ void Test() {
7171
#pragma acc loop num_gangs(1)
7272
for(int i = 5; i < 10;++i);
7373
}
74+
75+
void no_dupes_since_last_device_type() {
76+
// expected-error@+4{{OpenACC 'num_gangs' clause applies to 'device_type' 'radeon', which conflicts with previous 'num_gangs' clause}}
77+
// expected-note@+3{{active 'device_type' clause here}}
78+
// expected-note@+2{{previous 'num_gangs' clause is here}}
79+
// expected-note@+1{{which applies to 'device_type' clause here}}
80+
#pragma acc parallel device_type(nvidia, radeon) num_gangs(getS()) device_type(radeon) num_gangs(getS())
81+
;
82+
// expected-error@+4{{OpenACC 'num_gangs' clause applies to 'device_type' 'nvidia', which conflicts with previous 'num_gangs' clause}}
83+
// expected-note@+3{{active 'device_type' clause here}}
84+
// expected-note@+2{{previous 'num_gangs' clause is here}}
85+
// expected-note@+1{{which applies to 'device_type' clause here}}
86+
#pragma acc parallel device_type(nvidia) num_gangs(getS()) device_type(nvidia, radeon) num_gangs(getS())
87+
;
88+
}

clang/test/SemaOpenACC/compute-construct-num_workers-clause.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,18 @@ void Test() {
6060
#pragma acc loop num_workers(1)
6161
for(int i = 5; i < 10;++i);
6262
}
63+
64+
void no_dupes_since_last_device_type() {
65+
// expected-error@+4{{OpenACC 'num_workers' clause applies to 'device_type' 'radEon', which conflicts with previous 'num_workers' clause}}
66+
// expected-note@+3{{active 'device_type' clause here}}
67+
// expected-note@+2{{previous 'num_workers' clause is here}}
68+
// expected-note@+1{{which applies to 'device_type' clause here}}
69+
#pragma acc parallel device_type(nvidia, radeon) num_workers(getS()) device_type(radEon) num_workers(getS())
70+
;
71+
// expected-error@+4{{OpenACC 'num_workers' clause applies to 'device_type' 'nvidia', which conflicts with previous 'num_workers' clause}}
72+
// expected-note@+3{{active 'device_type' clause here}}
73+
// expected-note@+2{{previous 'num_workers' clause is here}}
74+
// expected-note@+1{{which applies to 'device_type' clause here}}
75+
#pragma acc parallel device_type(nvidia) num_workers(getS()) device_type(nvidia, radeon) num_workers(getS())
76+
;
77+
}

clang/test/SemaOpenACC/compute-construct-vector_length-clause.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,3 +60,18 @@ void Test() {
6060
#pragma acc loop vector_length(1)
6161
for(int i = 5; i < 10;++i);
6262
}
63+
64+
void no_dupes_since_last_device_type() {
65+
// expected-error@+4{{OpenACC 'vector_length' clause applies to 'device_type' 'radeon', which conflicts with previous 'vector_length' clause}}
66+
// expected-note@+3{{active 'device_type' clause here}}
67+
// expected-note@+2{{previous 'vector_length' clause is here}}
68+
// expected-note@+1{{which applies to 'device_type' clause here}}
69+
#pragma acc parallel device_type(nvidia, radeon) vector_length(getS()) device_type(radeon) vector_length(getS())
70+
;
71+
// expected-error@+4{{OpenACC 'vector_length' clause applies to 'device_type' 'nvidia', which conflicts with previous 'vector_length' clause}}
72+
// expected-note@+3{{active 'device_type' clause here}}
73+
// expected-note@+2{{previous 'vector_length' clause is here}}
74+
// expected-note@+1{{which applies to 'device_type' clause here}}
75+
#pragma acc parallel device_type(nvidia) vector_length(getS()) device_type(nvidia, radeon) vector_length(getS())
76+
;
77+
}

clang/test/SemaOpenACC/loop-construct-collapse-clause.cpp

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,4 +539,37 @@ void no_dupes_since_last_device_type() {
539539
#pragma acc loop collapse(1) device_type(*) collapse(1) device_type(nvidia) collapse(2)
540540
for(unsigned i = 0; i < 5; ++i)
541541
for(unsigned j = 0; j < 5; ++j);
542+
543+
// This one is ok, despite * being the 'all' value.
544+
#pragma acc loop device_type(*) collapse(1) device_type(nvidia) collapse(2)
545+
for(unsigned i = 0; i < 5; ++i)
546+
for(unsigned j = 0; j < 5; ++j);
547+
548+
#pragma acc loop device_type(nvidia) collapse(1) device_type(*) collapse(2)
549+
for(unsigned i = 0; i < 5; ++i)
550+
for(unsigned j = 0; j < 5; ++j);
551+
552+
// expected-error@+4{{OpenACC 'collapse' clause applies to 'device_type' '*', which conflicts with previous 'collapse' clause}}
553+
// expected-note@+3{{active 'device_type' clause here}}
554+
// expected-note@+2{{previous 'collapse' clause is here}}
555+
// expected-note@+1{{which applies to 'device_type' clause here}}
556+
#pragma acc loop device_type(*) collapse(1) device_type(*) collapse(2)
557+
for(unsigned i = 0; i < 5; ++i)
558+
for(unsigned j = 0; j < 5; ++j);
559+
560+
// expected-error@+4{{OpenACC 'collapse' clause applies to 'device_type' 'nvidia', which conflicts with previous 'collapse' clause}}
561+
// expected-note@+3{{active 'device_type' clause here}}
562+
// expected-note@+2{{previous 'collapse' clause is here}}
563+
// expected-note@+1{{which applies to 'device_type' clause here}}
564+
#pragma acc loop device_type(nviDia, radeon) collapse(1) device_type(nvidia) collapse(2)
565+
for(unsigned i = 0; i < 5; ++i)
566+
for(unsigned j = 0; j < 5; ++j);
567+
568+
// expected-error@+4{{OpenACC 'collapse' clause applies to 'device_type' 'radeon', which conflicts with previous 'collapse' clause}}
569+
// expected-note@+3{{active 'device_type' clause here}}
570+
// expected-note@+2{{previous 'collapse' clause is here}}
571+
// expected-note@+1{{which applies to 'device_type' clause here}}
572+
#pragma acc loop device_type(radeon) collapse(1) device_type(nvidia, radeon) collapse(2)
573+
for(unsigned i = 0; i < 5; ++i)
574+
for(unsigned j = 0; j < 5; ++j);
542575
}

clang/test/SemaOpenACC/loop-construct-tile-clause.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -419,4 +419,20 @@ void no_dupes_since_last_device_type() {
419419
#pragma acc loop tile(1) device_type(*) tile(1) device_type(nvidia) tile(2)
420420
for(unsigned i = 0; i < 5; ++i)
421421
for(unsigned j = 0; j < 5; ++j);
422+
423+
// expected-error@+4{{OpenACC 'tile' clause applies to 'device_type' 'nvidiA', which conflicts with previous 'tile' clause}}
424+
// expected-note@+3{{active 'device_type' clause here}}
425+
// expected-note@+2{{previous 'tile' clause is here}}
426+
// expected-note@+1{{which applies to 'device_type' clause here}}
427+
#pragma acc loop device_type(nvidia, radeon) tile(1) device_type(nvidiA) tile(2)
428+
for(unsigned i = 0; i < 5; ++i)
429+
for(unsigned j = 0; j < 5; ++j);
430+
431+
// expected-error@+4{{OpenACC 'tile' clause applies to 'device_type' 'radeon', which conflicts with previous 'tile' clause}}
432+
// expected-note@+3{{active 'device_type' clause here}}
433+
// expected-note@+2{{previous 'tile' clause is here}}
434+
// expected-note@+1{{which applies to 'device_type' clause here}}
435+
#pragma acc loop device_type(radeon) tile(1) device_type(nvidia, radeon) tile(2)
436+
for(unsigned i = 0; i < 5; ++i)
437+
for(unsigned j = 0; j < 5; ++j);
422438
}

0 commit comments

Comments
 (0)