Skip to content

Commit a83d336

Browse files
authored
[flang][OpenMP] Don't allow DO CONCURRENT inside of a loop nest (#144506)
I don't think DO CONCURRENT fits the definition of a Canonical Loop Nest (OpenMP 6.0 section 6.4.1). It is however explicitly allowed for the LOOP construct (6.0 section 13.8). There's some obscure language in OpenMP 6.0 for the LOOP construct: > If the collapsed loop is a DO CONCURRENT loop, neither the > data-sharing attribute clauses nor the collapse clause may be specified. From the surrounding context, I think "collapsed loop" just means the loop that the LOOP construct applies to. So I will interpret this to mean that DO CONCURRENT can only be used with the LOOP construct if it does not contain the COLLAPSE clause. This also fixes a bug where the associated clause was never cleared after it was set. Fixes #144178
1 parent 4b2ab14 commit a83d336

File tree

3 files changed

+71
-16
lines changed

3 files changed

+71
-16
lines changed

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 32 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "flang/Semantics/openmp-modifiers.h"
2424
#include "flang/Semantics/symbol.h"
2525
#include "flang/Semantics/tools.h"
26+
#include "llvm/Frontend/OpenMP/OMP.h.inc"
2627
#include "llvm/Support/Debug.h"
2728
#include <list>
2829
#include <map>
@@ -740,9 +741,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
740741
}
741742

742743
const parser::OmpClause *associatedClause{nullptr};
743-
void SetAssociatedClause(const parser::OmpClause &c) {
744-
associatedClause = &c;
745-
}
744+
void SetAssociatedClause(const parser::OmpClause *c) { associatedClause = c; }
746745
const parser::OmpClause *GetAssociatedClause() { return associatedClause; }
747746

748747
private:
@@ -1919,12 +1918,17 @@ std::int64_t OmpAttributeVisitor::GetAssociatedLoopLevelFromClauses(
19191918
}
19201919

19211920
if (orderedLevel && (!collapseLevel || orderedLevel >= collapseLevel)) {
1922-
SetAssociatedClause(*ordClause);
1921+
SetAssociatedClause(ordClause);
19231922
return orderedLevel;
19241923
} else if (!orderedLevel && collapseLevel) {
1925-
SetAssociatedClause(*collClause);
1924+
SetAssociatedClause(collClause);
19261925
return collapseLevel;
1927-
} // orderedLevel < collapseLevel is an error handled in structural checks
1926+
} else {
1927+
SetAssociatedClause(nullptr);
1928+
}
1929+
// orderedLevel < collapseLevel is an error handled in structural
1930+
// checks
1931+
19281932
return 1; // default is outermost loop
19291933
}
19301934

@@ -1952,9 +1956,31 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
19521956
ivDSA = Symbol::Flag::OmpLastPrivate;
19531957
}
19541958

1959+
bool isLoopConstruct{
1960+
GetContext().directive == llvm::omp::Directive::OMPD_loop};
1961+
const parser::OmpClause *clause{GetAssociatedClause()};
1962+
bool hasCollapseClause{
1963+
clause ? (clause->Id() == llvm::omp::OMPC_collapse) : false};
1964+
19551965
const auto &outer{std::get<std::optional<parser::DoConstruct>>(x.t)};
19561966
if (outer.has_value()) {
19571967
for (const parser::DoConstruct *loop{&*outer}; loop && level > 0; --level) {
1968+
if (loop->IsDoConcurrent()) {
1969+
// DO CONCURRENT is explicitly allowed for the LOOP construct so long as
1970+
// there isn't a COLLAPSE clause
1971+
if (isLoopConstruct) {
1972+
if (hasCollapseClause) {
1973+
// hasCollapseClause implies clause != nullptr
1974+
context_.Say(clause->source,
1975+
"DO CONCURRENT loops cannot be used with the COLLAPSE clause."_err_en_US);
1976+
}
1977+
} else {
1978+
auto &stmt =
1979+
std::get<parser::Statement<parser::NonLabelDoStmt>>(loop->t);
1980+
context_.Say(stmt.source,
1981+
"DO CONCURRENT loops cannot form part of a loop nest."_err_en_US);
1982+
}
1983+
}
19581984
// go through all the nested do-loops and resolve index variables
19591985
const parser::Name *iv{GetLoopIndex(*loop)};
19601986
if (iv) {

flang/test/Lower/OpenMP/Todo/omp-doconcurrent.f90

Lines changed: 0 additions & 10 deletions
This file was deleted.
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
!RUN: %python %S/../test_errors.py %s %flang -fopenmp
2+
3+
integer :: i, j
4+
!$omp parallel do collapse(2)
5+
do i = 1, 1
6+
! ERROR: DO CONCURRENT loops cannot form part of a loop nest.
7+
do concurrent (j = 1:2)
8+
print *, j
9+
end do
10+
end do
11+
12+
!$omp parallel do
13+
do i = 1, 1
14+
! This should not lead to an error because it is not part of a loop nest:
15+
do concurrent (j = 1:2)
16+
print *, j
17+
end do
18+
end do
19+
20+
!$omp parallel do
21+
! ERROR: DO CONCURRENT loops cannot form part of a loop nest.
22+
do concurrent (j = 1:2)
23+
print *, j
24+
end do
25+
26+
!$omp loop
27+
! Do concurrent is explicitly allowed inside of omp loop
28+
do concurrent (j = 1:2)
29+
print *, j
30+
end do
31+
32+
! ERROR: DO CONCURRENT loops cannot be used with the COLLAPSE clause.
33+
!$omp loop collapse(2)
34+
do i = 1, 1
35+
do concurrent (j = 1:2)
36+
print *, j
37+
end do
38+
end do
39+
end

0 commit comments

Comments
 (0)