Skip to content

Commit 3717048

Browse files
authored
[flang][Semantics][OpenMP] don't reduce variables in namelist (#110671)
This is allowed by the OpenMP and F23 standards. But variables in a namelist are not allowed in OpenMP privatisation. I suspect this was an oversight. If we allow this we run into problems masking the original symbol with the symbol for the reduction variable when the variable is accessed via a namelist initialised as a global variable. See #101907. One solution for this would be to force the namelist to always be initilized inside of the block in which it is used (therefore using the correct mapping for the reduction variable), but this could make some production applications slow. I tentatively think it is probably better to disallow a (perhaps mistaken) edge case of the standards with (I think) little practical use, than to make real applications slow in order to make this work. If reviewers would rather keep to the letter of the standard, see #109303 which implements the alternative solution. I'm open to either path forward. Fixes #101907
1 parent 15f9020 commit 3717048

File tree

5 files changed

+87
-0
lines changed

5 files changed

+87
-0
lines changed

flang/lib/Semantics/check-namelist.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,19 @@ void NamelistChecker::Leave(const parser::NamelistStmt &nmlStmt) {
3434
}
3535
}
3636

37+
void NamelistChecker::Leave(const parser::LocalitySpec::Reduce &x) {
38+
for (const parser::Name &name : std::get<std::list<parser::Name>>(x.t)) {
39+
Symbol *sym{name.symbol};
40+
// This is not disallowed by the standard, but would be difficult to
41+
// support. This has to go here not with the other checks for locality specs
42+
// in resolve-names.cpp so that it is done after the InNamelist flag is
43+
// applied.
44+
if (sym && sym->GetUltimate().test(Symbol::Flag::InNamelist)) {
45+
context_.Say(name.source,
46+
"NAMELIST variable '%s' not allowed in a REDUCE locality-spec"_err_en_US,
47+
name.ToString());
48+
}
49+
}
50+
}
51+
3752
} // namespace Fortran::semantics

flang/lib/Semantics/check-namelist.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ class NamelistChecker : public virtual BaseChecker {
1717
public:
1818
NamelistChecker(SemanticsContext &context) : context_{context} {}
1919
void Leave(const parser::NamelistStmt &);
20+
void Leave(const parser::LocalitySpec::Reduce &);
2021

2122
private:
2223
SemanticsContext &context_;

flang/lib/Semantics/resolve-directives.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2384,6 +2384,21 @@ void OmpAttributeVisitor::ResolveOmpObject(
23842384
GetContext().directive)
23852385
.str()));
23862386
}
2387+
if (ompFlag == Symbol::Flag::OmpReduction) {
2388+
const Symbol &ultimateSymbol{symbol->GetUltimate()};
2389+
// Using variables inside of a namelist in OpenMP reductions
2390+
// is allowed by the standard, but is not allowed for
2391+
// privatisation. This looks like an oversight. If the
2392+
// namelist is hoisted to a global, we cannot apply the
2393+
// mapping for the reduction variable: resulting in incorrect
2394+
// results. Disabling this hoisting could make some real
2395+
// production code go slower. See discussion in #109303
2396+
if (ultimateSymbol.test(Symbol::Flag::InNamelist)) {
2397+
context_.Say(name->source,
2398+
"Variable '%s' in NAMELIST cannot be in a REDUCTION clause"_err_en_US,
2399+
name->ToString());
2400+
}
2401+
}
23872402
if (GetContext().directive ==
23882403
llvm::omp::Directive::OMPD_target_data) {
23892404
checkExclusivelists(symbol, Symbol::Flag::OmpUseDevicePtr,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
! RUN: %python %S/../test_errors.py %s %flang -fopenmp
2+
! This is not actually disallowed by the OpenMP standard, but it is not allowed
3+
! for privatisation - this seems like an oversight.
4+
5+
module test
6+
integer :: a, b, c
7+
namelist /nlist1/ a, b
8+
end module
9+
10+
program omp_reduction
11+
use test
12+
13+
integer :: p(10) ,q(10)
14+
namelist /nlist2/ c, d
15+
16+
a = 5
17+
b = 10
18+
c = 100
19+
20+
!ERROR: Variable 'd' in NAMELIST cannot be in a REDUCTION clause
21+
!ERROR: Variable 'a' in NAMELIST cannot be in a REDUCTION clause
22+
!$omp parallel reduction(+:d) reduction(+:a)
23+
d = a + b
24+
a = d
25+
!$omp end parallel
26+
27+
call sb()
28+
29+
contains
30+
subroutine sb()
31+
namelist /nlist3/ p, q
32+
33+
!ERROR: Variable 'p' in NAMELIST cannot be in a REDUCTION clause
34+
!ERROR: Variable 'q' in NAMELIST cannot be in a REDUCTION clause
35+
!$omp parallel reduction(+:p) reduction(+:q)
36+
p = c * b
37+
q = p * d
38+
!$omp end parallel
39+
40+
write(*, nlist1)
41+
write(*, nlist2)
42+
write(*, nlist3)
43+
44+
end subroutine
45+
46+
end program omp_reduction

flang/test/Semantics/resolve123.f90

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,3 +77,13 @@ subroutine s9()
7777
do concurrent(i=1:5) reduce(+:i)
7878
end do
7979
end subroutine s9
80+
81+
subroutine s10()
82+
! Cannot have variable inside of a NAMELIST in a REDUCE locality spec
83+
integer :: k
84+
namelist /nlist1/ k
85+
!ERROR: NAMELIST variable 'k' not allowed in a REDUCE locality-spec
86+
do concurrent(i=1:5) reduce(+:k)
87+
k = k + i
88+
end do
89+
end subroutine s10

0 commit comments

Comments
 (0)