[OPENMP]Fix PR46347: several ordered directives in a single region.

Summary:
According to OpenMP, During execution of an iteration of a worksharing-loop or a loop nest within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread must not execute more than one ordered region corresponding to an ordered construct without a depend clause.
Need to report an error in this case.

Reviewers: jdoerfert

Subscribers: yaxunl, guansong, sstefan1, cfe-commits, caomhin

Tags: #clang

Differential Revision: https://reviews.llvm.org/D81951
This commit is contained in:
Alexey Bataev 2020-06-16 13:16:08 -04:00
parent ff628f5f5e
commit 3488e8c21c
3 changed files with 62 additions and 7 deletions

View File

@ -9937,10 +9937,10 @@ def err_omp_prohibited_region_critical_same_name : Error<
"cannot nest 'critical' regions having the same name %0">;
def note_omp_previous_critical_region : Note<
"previous 'critical' region starts here">;
def err_omp_several_scan_directives_in_region : Error<
"exactly one 'scan' directive must appear in the loop body of an enclosing directive">;
def note_omp_previous_scan_directive : Note<
"previous 'scan' directive used here">;
def err_omp_several_directives_in_region : Error<
"exactly one '%0' directive must appear in the loop body of an enclosing directive">;
def note_omp_previous_directive : Note<
"previous '%0' directive used here">;
def err_omp_sections_not_compound_stmt : Error<
"the statement for '#pragma omp sections' must be a compound statement">;
def err_omp_parallel_sections_not_compound_stmt : Error<

View File

@ -169,6 +169,7 @@ private:
bool LoopStart = false;
bool BodyComplete = false;
SourceLocation PrevScanLocation;
SourceLocation PrevOrderedLocation;
SourceLocation InnerTeamsRegionLoc;
/// Reference to the taskgroup task_reduction reference expression.
Expr *TaskgroupReductionRef = nullptr;
@ -848,6 +849,21 @@ public:
const SharingMapTy *Top = getSecondOnStackOrNull();
return Top ? Top->PrevScanLocation : SourceLocation();
}
/// Mark that parent region already has ordered directive.
void setParentHasOrderedDirective(SourceLocation Loc) {
if (SharingMapTy *Parent = getSecondOnStackOrNull())
Parent->PrevOrderedLocation = Loc;
}
/// Return true if current region has inner ordered construct.
bool doesParentHasOrderedDirective() const {
const SharingMapTy *Top = getSecondOnStackOrNull();
return Top ? Top->PrevOrderedLocation.isValid() : false;
}
/// Returns the location of the previously specified ordered directive.
SourceLocation getParentOrderedDirectiveLoc() const {
const SharingMapTy *Top = getSecondOnStackOrNull();
return Top ? Top->PrevOrderedLocation : SourceLocation();
}
/// Set collapse value for the region.
void setAssociatedLoops(unsigned Val) {
@ -9187,9 +9203,10 @@ StmtResult Sema::ActOnOpenMPScanDirective(ArrayRef<OMPClause *> Clauses,
// Check that only one instance of scan directives is used in the same outer
// region.
if (DSAStack->doesParentHasScanDirective()) {
Diag(StartLoc, diag::err_omp_several_scan_directives_in_region);
Diag(StartLoc, diag::err_omp_several_directives_in_region) << "scan";
Diag(DSAStack->getParentScanDirectiveLoc(),
diag::note_omp_previous_scan_directive);
diag::note_omp_previous_directive)
<< "scan";
return StmtError();
}
DSAStack->setParentHasScanDirective(StartLoc);
@ -9265,6 +9282,22 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
if ((!AStmt && !DependFound) || ErrorFound)
return StmtError();
// OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
// During execution of an iteration of a worksharing-loop or a loop nest
// within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
// must not execute more than one ordered region corresponding to an ordered
// construct without a depend clause.
if (!DependFound) {
if (DSAStack->doesParentHasOrderedDirective()) {
Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
Diag(DSAStack->getParentOrderedDirectiveLoc(),
diag::note_omp_previous_directive)
<< "ordered";
return StmtError();
}
DSAStack->setParentHasOrderedDirective(StartLoc);
}
if (AStmt) {
assert(isa<CapturedStmt>(AStmt) && "Captured statement expected");

View File

@ -61,6 +61,17 @@ T foo() {
foo();
}
}
#pragma omp for ordered
for (int i = 0; i < 10; ++i) {
#pragma omp ordered // expected-note {{previous 'ordered' directive used here}}
{
foo();
}
#pragma omp ordered // expected-error {{exactly one 'ordered' directive must appear in the loop body of an enclosing directive}}
{
foo();
}
}
#pragma omp ordered simd simd // expected-error {{directive '#pragma omp ordered' cannot contain more than one 'simd' clause}}
{
foo();
@ -79,7 +90,18 @@ T foo() {
foo();
}
}
#pragma omp for simd
#pragma omp simd
for (int i = 0; i < 10; ++i) {
#pragma omp ordered simd // expected-note {{previous 'ordered' directive used here}}
{
foo();
}
#pragma omp ordered simd // expected-error {{exactly one 'ordered' directive must appear in the loop body of an enclosing directive}}
{
foo();
}
}
#pragma omp for simd
for (int i = 0; i < 10; ++i) {
#pragma omp ordered // expected-error {{OpenMP constructs may not be nested inside a simd region}}
{